В момента се задълбочавам в анализатора на PostgreSQL, преписването на заявки и планирането на заявки, като част от работата по сигурността на ниво ред за проекта AXLE. Тъй като забелязах, че има страхотна документация за цялостната структура и поток, но не много за някои от детайлите, реших да започна да публикувам за някои от по-объркващите ъгли.
Ако не се интересувате от изходния код на PostgreSQL и неговата вътрешна работа, можете да спрете да четете сега.
изброяване
Днешната тема е терминът „resjunk“, който се отнася до resjunk атрибут на целевия списък. Ще видите този термин в целия плановик и пренаписване, обикновено като предполагаемо знание. Името не е особено полезно.
изхвърляне колоните са описани в src/backend/executor/execJunk.c , където има умерено подробен коментар. Това обаче всъщност не обяснява всеобхватните идеи.
Концепцията е, че понякога PostgreSQL трябва да следи информацията за всеки кортеж, която не е част от изхода на заявката. Може да е ключ за сортиране, който не е част от списъка за избор, междинен резултат от подзаявка, която се използва като филтър, след което се отхвърля, или може да е вътрешна колона като ctid която не е изложена на потребителите.
Възлите на плана имат целеви списъци – това са списъци на колоните, изведени от този възел на плана. За прост тест SELECT a, b FROM колоните a и b ще се появи в целевия списък на възела на index или seqscan план за заявката. Можете сами да наблюдавате това, като активирате записването на плана според следния изрязан изход:
regress=> CREATE TABLE regress=> SET enable_print_plan = on; regress=> SET client_min_messages = debug; regress=> SELECT a, b FROM test; LOG: plan: DETAIL: {PLANNEDSTMT :commandType 1 :queryId 0 .... :planTree {SEQSCAN :startup_cost 0.00 :total_cost 29.40 :plan_rows 1940 :plan_width 12 :targetlist ( {TARGETENTRY :expr {VAR :varno 1 :varattno 1 ... :location 7 } ... :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 2 ... :location 10 } .... :resjunk false } ) :qual :lefttree :righttree :initPlan :extParam (b) :allParam (b) :scanrelid 1 } :rtable ( {RTE :alias :eref {ALIAS :aliasname test :colnames ("a" "b") } ... :selectedCols (b 9 10) :modifiedCols (b) } ) .... }
Това е подробният план за:
QUERY PLAN -------------------------------------------------------- Seq Scan on test (cost=0.00..29.40 rows=1940 width=8)
В него ще видите, че SELECT има два записа в целевия списък, по един за всяка колона. Нито resjunk тъй като и двете се извеждат от заявката.
Ами ако добавим сортиране по колона c , което не е в SELECT -list, ще видим нова колона, добавена към целевия списък и маркирана като препращане:
regress=> SELECT a, b FROM test ORDER BY c; LOG: plan: DETAIL: {PLANNEDSTMT :commandType 1 .... :planTree {SORT .... :targetlist ( {TARGETENTRY :expr {VAR :varno 65001 :varattno 1 ... } :resno 1 :resname a ... :resjunk false } {TARGETENTRY :expr {VAR :varno 65001 :varattno 2 ... } :resno 2 :resname b .... :resjunk false } {TARGETENTRY :expr {VAR :varno 65001 :varattno 3 ... } :resno 3 :resname .... :resjunk true } ) :qual :lefttree {SEQSCAN ... :targetlist ( {TARGETENTRY :expr {VAR :varno 1 :varattno 1 ... } :resno 1 ... :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 2 ... } :resno 2 ... :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 3 ... } :resno 3 ... :resjunk true } ) .... } :rtable ( {RTE :alias :eref {ALIAS :aliasname test :colnames ("a" "b" "c") } .... :selectedCols (b 9 10 11) :modifiedCols (b) } ) .... }
за плана на заявката:
QUERY PLAN --------------------------------------------------------------- Sort (cost=135.34..140.19 rows=1940 width=12) Sort Key: c -> Seq Scan on test (cost=0.00..29.40 rows=1940 width=12) (3 rows)
Така че c е маркиран като отпаднала защото това е ключ за сортиране, който не е част от крайния изход на плана.
Ще видите също ctid с маркировка отпаднала в АКТУАЛИЗИРАНЕ и ИЗТРИВАНЕ планове по подобни причини – прочетената част на плана извлича редовете за модифициране и техните идентификатори на кортежи; те се изтеглят в най-външната МОДИФИКАЦИЯ възел на плана, който актуализира реда, за да го маркира като изтрит и, ако е актуализация, вмъква нова версия на реда.
Изследванията, довели до тези резултати, са получили финансиране от Седмата рамкова програма на Европейския съюз (FP7/2007-2013) по споразумение за отпускане на безвъзмездни средства № 318633