クエリのパース処理
これからしばらくSQLのパースから実行までを見ていこうかなと思う。結合、サブクエリ、集約等がどう処理されるか理解したい。それと集合論的な考え方を身につけたいなぁ。
とりあえずはNested Loop Join が行われるSQLで考える。パースツリー、クエリツリー、プランツリーのノードをデバッグ用の関数pprint()で出力してみた。パースツリー、クエリツリー、プランツリーの用語はhttp://www2b.biglobe.ne.jp/~caco/webdb-pdfs/vol27.pdfを参考にした。
どんなノード(のデータ構造)があるのか把握するところから始めようなかな。
SQL
pgbenchでつくったテーブルをつかっている。
select * from accounts a inner join branches b on a.bid = b.bid where a.aid = 100
実行計画
explainした結果。ちゃんとNested Loop Joinになっている。
Nested Loop (cost=0.00..9.58 rows=1 width=461) Join Filter: (a.bid = b.bid) -> Index Scan using accounts_pkey1 on accounts a (cost=0.00..8.36 rows=1 width=97) Index Cond: (aid = 100) -> Seq Scan on branches b (cost=0.00..1.10 rows=10 width=364)
生のパースツリー
pg_parse_query()の後でgdbで止めてpprint()した。
{SELECT :distinctClause <> :intoClause <> :targetList ( {RESTARGET :name <> :indirection <> :val {COLUMNREF :fields ("*") :location 7 } :location 7 } ) :fromClause ( {JOINEXPR :jointype 0 :isNatural false :larg {RANGEVAR :schemaname <> :relname accounts :inhOpt 2 :istemp false :alias {ALIAS :aliasname a :colnames <> } } :rarg {RANGEVAR :schemaname <> :relname branches :inhOpt 2 :istemp false :alias {ALIAS :aliasname b :colnames <> } } :using <> :quals {AEXPR :name ("=") :lexpr {COLUMNREF :fields ("a" "bid") :location 50 } :rexpr {COLUMNREF :fields ("b" "bid") :location 58 } :location 56 } :alias <> :rtindex 0 } ) :whereClause {AEXPR :name ("=") :lexpr {COLUMNREF :fields ("a" "aid") :location 70 } :rexpr {A_CONST :val 100 :typename <> } :location 76 } :groupClause <> :havingClause <> :valuesLists <> :sortClause <> :limitOffset <> :limitCount <> :lockingClause <> :op 0 :all false :larg <> :rarg <> }
リライト後のクエリツリー
pg_analyze_and_rewrite()の後でgdbで止めてpprint()した。長い。
{QUERY :commandType 1 :querySource 0 :canSetTag true :utilityStmt <> :resultRelation 0 :intoClause <> :hasAggs false :hasSubLinks false :rtable ( {RTE :alias {ALIAS :aliasname a :colnames <> } :eref {ALIAS :aliasname a :colnames ("aid" "bid" "abalance" "filler") } :rtekind 0 :relid 16453 :inh true :inFromCl true :requiredPerms 2 :checkAsUser 0 } {RTE :alias {ALIAS :aliasname b :colnames <> } :eref {ALIAS :aliasname b :colnames ("bid" "bbalance" "filler") } :rtekind 0 :relid 16447 :inh true :inFromCl true :requiredPerms 2 :checkAsUser 0 } {RTE :alias <> :eref {ALIAS :aliasname unnamed_join :colnames ("aid" "bid" "abalance" "filler" "bid" "bbalance" "filler") } :rtekind 2 :jointype 0 :joinaliasvars ( {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } {VAR :varno 1 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 2 } {VAR :varno 1 :varattno 3 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 3 } {VAR :varno 1 :varattno 4 :vartype 1042 :vartypmod 88 :varlevelsup 0 :varnoold 1 :varoattno 4 } {VAR :varno 2 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 1 } {VAR :varno 2 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 2 } {VAR :varno 2 :varattno 3 :vartype 1042 :vartypmod 92 :varlevelsup 0 :varnoold 2 :varoattno 3 } ) :inh false :inFromCl true :requiredPerms 2 :checkAsUser 0 } :jointree {FROMEXPR :fromlist ( {JOINEXPR :jointype 0 :isNatural false :larg {RANGETBLREF :rtindex 1 } :rarg {RANGETBLREF :rtindex 2 } :using <> :quals {OPEXPR :opno 96 :opfuncid 65 :opresulttype 16 :opretset false :args ( {VAR :varno 1 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 2 } {VAR :varno 2 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 1 } ) } :alias <> :rtindex 3 } ) :quals {OPEXPR :opno 96 :opfuncid 65 :opresulttype 16 :opretset false :args ( {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } {CONST :consttype 23 :consttypmod -1 :constlen 4 :constbyval true :constisnull false :constvalue 4 [ 100 0 0 0 ] } ) } } :targetList ( {TARGETENTRY :expr {VAR :varno 3 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 1 } :resno 1 :resname aid :ressortgroupref 0 :resorigtbl 16453 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 2 } :resno 2 :resname bid :ressortgroupref 0 :resorigtbl 16453 :resorigcol 2 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 3 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 3 } :resno 3 :resname abalance :ressortgroupref 0 :resorigtbl 16453 :resorigcol 3 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 4 :vartype 1042 :vartypmod 88 :varlevelsup 0 :varnoold 3 :varoattno 4 } :resno 4 :resname filler :ressortgroupref 0 :resorigtbl 16453 :resorigcol 4 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 5 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 5 } :resno 5 :resname bid :ressortgroupref 0 :resorigtbl 16447 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 6 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 3 :varoattno 6 } :resno 6 :resname bbalance :ressortgroupref 0 :resorigtbl 16447 :resorigcol 2 :resjunk false } {TARGETENTRY :expr {VAR :varno 3 :varattno 7 :vartype 1042 :vartypmod 92 :varlevelsup 0 :varnoold 3 :varoattno 7 } :resno 7 :resname filler :ressortgroupref 0 :resorigtbl 16447 :resorigcol 3 :resjunk false } ) :returningList <> :groupClause <> :havingQual <> :distinctClause <> :sortClause <> :limitOffset <> :limitCount <> :rowMarks <> :setOperations <> }
プランツリー
pg_plan_queries()が終わった後でgdbで止めてpprint()した。これも長いよ。
{PLANNEDSTMT :commandType 1 :canSetTag true :planTree {NESTLOOP :startup_cost 0.00 :total_cost 9.58 :plan_rows 1 :plan_width 461 :targetlist ( {TARGETENTRY :expr {VAR :varno 65001 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } :resno 1 :resname aid :ressortgroupref 0 :resorigtbl 16453 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 65001 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 2 } :resno 2 :resname bid :ressortgroupref 0 :resorigtbl 16453 :resorigcol 2 :resjunk false } {TARGETENTRY :expr {VAR :varno 65001 :varattno 3 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 3 } :resno 3 :resname abalance :ressortgroupref 0 :resorigtbl 16453 :resorigcol 3 :resjunk false } {TARGETENTRY :expr {VAR :varno 65001 :varattno 4 :vartype 1042 :vartypmod 88 :varlevelsup 0 :varnoold 1 :varoattno 4 } :resno 4 :resname filler :ressortgroupref 0 :resorigtbl 16453 :resorigcol 4 :resjunk false } {TARGETENTRY :expr {VAR :varno 65000 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 1 } :resno 5 :resname bid :ressortgroupref 0 :resorigtbl 16447 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 65000 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 2 } :resno 6 :resname bbalance :ressortgroupref 0 :resorigtbl 16447 :resorigcol 2 :resjunk false } {TARGETENTRY :expr {VAR :varno 65000 :varattno 3 :vartype 1042 :vartypmod 92 :varlevelsup 0 :varnoold 2 :varoattno 3 } :resno 7 :resname filler :ressortgroupref 0 :resorigtbl 16447 :resorigcol 3 :resjunk false } ) :qual <> :lefttree {INDEXSCAN :startup_cost 0.00 :total_cost 8.36 :plan_rows 1 :plan_width 97 :targetlist ( {TARGETENTRY :expr {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } :resno 1 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 2 } :resno 2 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 3 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 3 } :resno 3 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 4 :vartype 1042 :vartypmod 88 :varlevelsup 0 :varnoold 1 :varoattno 4 } :resno 4 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } ) :qual <> :lefttree <> :righttree <> :initPlan <> :extParam (b) :allParam (b) :scanrelid 1 :indexid 16464 :indexqual ( {OPEXPR :opno 96 :opfuncid 65 :opresulttype 16 :opretset false :args ( {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } {CONST :consttype 23 :consttypmod -1 :constlen 4 :constbyval true :constisnull false :constvalue 4 [ 100 0 0 0 ] } ) } ) :indexqualorig ( {OPEXPR :opno 96 :opfuncid 65 :opresulttype 16 :opretset false :args ( {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 1 } {CONST :consttype 23 :consttypmod -1 :constlen 4 :constbyval true :constisnull false :constvalue 4 [ 100 0 0 0 ] } ) } ) :indexstrategy (i 3) :indexsubtype (o 23) :indexorderdir 1 } :righttree {SEQSCAN :startup_cost 0.00 :total_cost 1.10 :plan_rows 10 :plan_width 364 :targetlist ( {TARGETENTRY :expr {VAR :varno 2 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 1 } :resno 1 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } {TARGETENTRY :expr {VAR :varno 2 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 2 } :resno 2 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } {TARGETENTRY :expr {VAR :varno 2 :varattno 3 :vartype 1042 :vartypmod 92 :varlevelsup 0 :varnoold 2 :varoattno 3 } :resno 3 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } ) :qual <> :lefttree <> :righttree <> :initPlan <> :extParam (b) :allParam (b) :scanrelid 2 } :initPlan <> :extParam (b) :allParam (b) :jointype 0 :joinqual ( {OPEXPR :opno 96 :opfuncid 65 :opresulttype 16 :opretset false :args ( {VAR :varno 65001 :varattno 2 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 1 :varoattno 2 } {VAR :varno 65000 :varattno 1 :vartype 23 :vartypmod -1 :varlevelsup 0 :varnoold 2 :varoattno 1 } ) } ) } :rtable ( {RTE :alias {ALIAS :aliasname a :colnames <> } :eref {ALIAS :aliasname a :colnames ("aid" "bid" "abalance" "filler") } :rtekind 0 :relid 16453 :inh false :inFromCl true :requiredPerms 2 :checkAsUser 0 } {RTE :alias {ALIAS :aliasname b :colnames <> } :eref {ALIAS :aliasname b :colnames ("bid" "bbalance" "filler") } :rtekind 0 :relid 16447 :inh false :inFromCl true :requiredPerms 2 :checkAsUser 0 } {RTE :alias <> :eref {ALIAS :aliasname unnamed_join :colnames ("aid" "bid" "abalance" "filler" "bid" "bbalance" "filler") } :rtekind 2 :jointype 0 :joinaliasvars <> :inh false :inFromCl true :requiredPerms 2 :checkAsUser 0 } ) :resultRelations <> :utilityStmt <> :intoClause <> :subplans <> :rewindPlanIDs (b) :returningLists <> :rowMarks <> :relationOids (o 16453 16447) :nParamExec 0 }