上一章節(jié)已介紹了如何識(shí)別分區(qū)表并找到所有的分區(qū)子表以及函數(shù)expand_inherited_tables的主要實(shí)現(xiàn)邏輯,該函數(shù)把子表信息放在root(PlannerInfo)->append_rel_list鏈表中就缆。為了更好的理解相關(guān)的邏輯,本節(jié)重點(diǎn)介紹分區(qū)表查詢(xún)相關(guān)的重要數(shù)據(jù)結(jié)構(gòu),包括RelOptInfo/PlannerInfo/AppendRelInfo.
一瓣铣、數(shù)據(jù)結(jié)構(gòu)
RelOptInfo
RelOptInfo是規(guī)劃器/優(yōu)化器使用的關(guān)系信息結(jié)構(gòu)體
在規(guī)劃過(guò)程中已存在的基表或者是在關(guān)系運(yùn)算過(guò)程中產(chǎn)生的中間關(guān)系或者是最終產(chǎn)生的關(guān)系,都使用RelOptInfo結(jié)構(gòu)體進(jìn)行封裝表示.
查詢(xún)分區(qū)表時(shí)該結(jié)構(gòu)體中的part_scheme存儲(chǔ)分區(qū)的schema,nparts存儲(chǔ)分區(qū)數(shù),boundinfo是分區(qū)邊界信息,partition_qual是分區(qū)約束條件,part_rels是分區(qū)表中每個(gè)分區(qū)的每個(gè)分區(qū)的RelOptInfo,partexprs是分區(qū)鍵表達(dá)式,partitioned_child_rels是關(guān)系中未修剪(unpruned)分區(qū)的RT索引.unpruned是指查詢(xún)分區(qū)表時(shí),涉及的相關(guān)分區(qū),比如 where c1 = 1 OR c1 = 2涉及的分區(qū)只有t_hash_partition_1和t_hash_partition_3,則在partitioned_child_rels中只有這兩個(gè)分區(qū)的信息.
如何pruned,下節(jié)介紹
/*----------
* RelOptInfo
* Per-relation information for planning/optimization
* 規(guī)劃器/優(yōu)化器使用的關(guān)系信息結(jié)構(gòu)體
*
* For planning purposes, a "base rel" is either a plain relation (a table)
* or the output of a sub-SELECT or function that appears in the range table.
* In either case it is uniquely identified by an RT index. A "joinrel"
* is the joining of two or more base rels. A joinrel is identified by
* the set of RT indexes for its component baserels. We create RelOptInfo
* nodes for each baserel and joinrel, and store them in the PlannerInfo's
* simple_rel_array and join_rel_list respectively.
* 出于計(jì)劃目的丘薛,“base rel”要么是一個(gè)普通關(guān)系(表)蜈敢,
* 要么是出現(xiàn)在范圍表中的子查詢(xún)或函數(shù)的輸出。
* 在這兩種情況下,它都是由RT索引惟一標(biāo)識(shí)的。
* "joinrel"是兩個(gè)或兩個(gè)以上的base rels連接。
* 一個(gè)joinrel是由它的baserels的RT索引集標(biāo)識(shí)弄兜。
* 我們?yōu)槊總€(gè)baserel和joinrel分別創(chuàng)建RelOptInfo節(jié)點(diǎn),
* 并將它們分別存儲(chǔ)在PlannerInfo的simple_rel_array和join_rel_list中。
*
* Note that there is only one joinrel for any given set of component
* baserels, no matter what order we assemble them in; so an unordered
* set is the right datatype to identify it with.
* 請(qǐng)注意替饿,對(duì)于任何給定的base rels语泽,無(wú)論我們以何種順序組合它們,
* 都只有一個(gè)連接件;因此视卢,一個(gè)無(wú)序的集合正好是標(biāo)識(shí)它的數(shù)據(jù)類(lèi)型踱卵。
*
* We also have "other rels", which are like base rels in that they refer to
* single RT indexes; but they are not part of the join tree, and are given
* a different RelOptKind to identify them.
* Currently the only kind of otherrels are those made for member relations
* of an "append relation", that is an inheritance set or UNION ALL subquery.
* An append relation has a parent RTE that is a base rel, which represents
* the entire append relation. The member RTEs are otherrels. The parent
* is present in the query join tree but the members are not. The member
* RTEs and otherrels are used to plan the scans of the individual tables or
* subqueries of the append set; then the parent baserel is given Append
* and/or MergeAppend paths comprising the best paths for the individual
* member rels. (See comments for AppendRelInfo for more information.)
* 同時(shí)存在“other rels”,類(lèi)似于base rels据过,它們同樣都指向單個(gè)RT索引;
* 但是它們不是join樹(shù)的一部分惋砂,并且被賦予不同的RelOptKind來(lái)標(biāo)識(shí)它們。
* 目前唯一的其他類(lèi)型是那些為“append relation”的成員關(guān)系而創(chuàng)建的绳锅,
* 即繼承集或UNION ALL子查詢(xún)西饵。
* 一個(gè)append relation有一個(gè)父RTE,它是一個(gè)基礎(chǔ)rel鳞芙,表示整個(gè)append relation眷柔。
* 其他成員RTEs是otherrel.。
* 父節(jié)點(diǎn)存在于查詢(xún)的連接樹(shù)中原朝,但成員無(wú)需存儲(chǔ)在連接樹(shù)中驯嘱。
* 成員RTEs和otherrels用于計(jì)劃對(duì)append set的單表或子查詢(xún)的掃描;
* 然后給出parent base rel的APPEND路徑和/或MergeAppend路徑,這些路徑包含單個(gè)成員rels的最佳路徑竿拆。
* (更多信息請(qǐng)參見(jiàn)AppendRelInfo的注釋宙拉。)
*
* At one time we also made otherrels to represent join RTEs, for use in
* handling join alias Vars. Currently this is not needed because all join
* alias Vars are expanded to non-aliased form during preprocess_expression.
* 曾經(jīng),還制作了其他的樹(shù)來(lái)表示連接rte丙笋,用于處理連接別名Vars。
* 目前不需要這樣做煌贴,因?yàn)樵趐reprocess_expression期間御板,所有連接別名Vars都被擴(kuò)展為非別名形式。
*
* We also have relations representing joins between child relations of
* different partitioned tables. These relations are not added to
* join_rel_level lists as they are not joined directly by the dynamic
* programming algorithm.
* 還有表示不同分區(qū)表的子關(guān)系之間的連接的關(guān)系牛郑。
* 這些關(guān)系不會(huì)添加到j(luò)oin_rel_level鏈表中怠肋,因?yàn)閯?dòng)態(tài)規(guī)劃算法不會(huì)直接連接它們。
*
* There is also a RelOptKind for "upper" relations, which are RelOptInfos
* that describe post-scan/join processing steps, such as aggregation.
* Many of the fields in these RelOptInfos are meaningless, but their Path
* fields always hold Paths showing ways to do that processing step.
* 還有一種RelOptKind表示“upper”關(guān)系淹朋,
* 即描述掃描/連接后處理步驟(如聚合)的RelOptInfos笙各。
* 這些RelOptInfos中的許多字段都是沒(méi)有意義的,
* 但是它們的Path字段總是包含顯示執(zhí)行該處理步驟的路徑础芍。
*
* Lastly, there is a RelOptKind for "dead" relations, which are base rels
* that we have proven we don't need to join after all.
* 最后杈抢,還有一種關(guān)系是“DEAD”的關(guān)系,在規(guī)劃期間已經(jīng)證明不需要把此關(guān)系加入連接仑性。
*
* Parts of this data structure are specific to various scan and join
* mechanisms. It didn't seem worth creating new node types for them.
* 該數(shù)據(jù)結(jié)構(gòu)的某些部分特定于各種掃描和連接機(jī)制惶楼。
* 但似乎不值得為它們創(chuàng)建新的節(jié)點(diǎn)類(lèi)型。
*
* relids - Set of base-relation identifiers; it is a base relation
* if there is just one, a join relation if more than one
* relids - 基礎(chǔ)關(guān)系標(biāo)識(shí)符的集合;如只有一個(gè)則為基礎(chǔ)關(guān)系,
* 如有多個(gè)則為連接關(guān)系
* rows - estimated number of tuples in the relation after restriction
* clauses have been applied (ie, output rows of a plan for it)
* rows - 應(yīng)用約束條件子句后關(guān)系中元組的估算數(shù)目(即計(jì)劃的輸出行數(shù))
* consider_startup - true if there is any value in keeping plain paths for
* this rel on the basis of having cheap startup cost
* consider_startup - 如果在具有低啟動(dòng)成本的基礎(chǔ)上為這個(gè)rel保留訪問(wèn)路徑有價(jià)值,則為真
* consider_param_startup - the same for parameterized paths
* consider_param_startup - 與parameterized訪問(wèn)路徑一致
* reltarget - Default Path output tlist for this rel; normally contains
* Var and PlaceHolderVar nodes for the values we need to
* output from this relation.
* List is in no particular order, but all rels of an
* appendrel set must use corresponding orders.
* NOTE: in an appendrel child relation, may contain
* arbitrary expressions pulled up from a subquery!
* reltarget - 該rel的默認(rèn)路徑輸出投影列;通常會(huì)包含Var和PlaceHolderVar
* pathlist - List of Path nodes, one for each potentially useful
* method of generating the relation
* 訪問(wèn)路徑節(jié)點(diǎn)鏈表, 存儲(chǔ)每一種可能有用的生成關(guān)系的方法
* ppilist - ParamPathInfo nodes for parameterized Paths, if any
* 參數(shù)化路徑的ParamPathInfo節(jié)點(diǎn)(如果有的話(huà))
* cheapest_startup_path - the pathlist member with lowest startup cost
* (regardless of ordering) among the unparameterized paths;
* or NULL if there is no unparameterized path
* 在非參數(shù)化路徑中啟動(dòng)成本最低(無(wú)論順序如何)的路徑鏈表成員;
* 如果沒(méi)有非參數(shù)化路徑歼捐,則為NULL
* cheapest_total_path - the pathlist member with lowest total cost
* (regardless of ordering) among the unparameterized paths;
* or if there is no unparameterized path, the path with lowest
* total cost among the paths with minimum parameterization
* 在非參數(shù)化路徑中總成本最低(無(wú)論順序如何)的路徑列表成員;
* 如果沒(méi)有非參數(shù)化路徑何陆,則在參數(shù)化最少的路徑中總成本最低的路徑
* cheapest_unique_path - for caching cheapest path to produce unique
* (no duplicates) output from relation; NULL if not yet requested
* 用于緩存最便宜的路徑,以便從關(guān)系中產(chǎn)生唯一(無(wú)重復(fù))輸出;
* 如果無(wú)此要求豹储,則為NULL
* cheapest_parameterized_paths - best paths for their parameterizations;
* always includes cheapest_total_path, even if that's unparameterized
* 參數(shù)化的最佳路徑;總是包含cheapest_total_path贷盲,即使它是非參數(shù)化的
* direct_lateral_relids - rels this rel has direct LATERAL references to
* 該rel直接LATERAL依賴(lài)的rels
* lateral_relids - required outer rels for LATERAL, as a Relids set
* (includes both direct and indirect lateral references)
* LATERAL所需的外部rels,作為Relids集合(包括直接和間接的側(cè)向參考)
*
* If the relation is a base relation it will have these fields set:
* 如果關(guān)系是一個(gè)基本關(guān)系剥扣,它將設(shè)置這些字段:
* relid - RTE index (this is redundant with the relids field, but
* is provided for convenience of access)
* RTE索引(這對(duì)于relids字段來(lái)說(shuō)是冗余的晃洒,但是為了方便訪問(wèn)而提供)
* rtekind - copy of RTE's rtekind field
* RTE's rtekind字段的拷貝
* min_attr, max_attr - range of valid AttrNumbers for rel
* 關(guān)系有效AttrNumbers的范圍(最大/最小編號(hào))
* attr_needed - array of bitmapsets indicating the highest joinrel
* in which each attribute is needed; if bit 0 is set then
* the attribute is needed as part of final targetlist
* 位圖集數(shù)組,表示每個(gè)屬性所需的最高層joinrel;
* 如果設(shè)置為0朦乏,則需要將該屬性作為最終targetlist的一部分
* attr_widths - cache space for per-attribute width estimates;
* zero means not computed yet
* 用于每個(gè)屬性寬度估計(jì)的緩存空間;0表示還沒(méi)有計(jì)算
* lateral_vars - lateral cross-references of rel, if any (list of
* Vars and PlaceHolderVars)
* rel的lateral交叉參照球及,如果有的話(huà)(Vars和PlaceHolderVars鏈表)
* lateral_referencers - relids of rels that reference this one laterally
* (includes both direct and indirect lateral references)
* lateral依賴(lài)此關(guān)系的relids(包括直接&間接lateral依賴(lài))
* indexlist - list of IndexOptInfo nodes for relation's indexes
* (always NIL if it's not a table)
* 關(guān)系索引的IndexOptInfo節(jié)點(diǎn)鏈表(如果不是表,總是NIL)
* pages - number of disk pages in relation (zero if not a table)
* 關(guān)系的磁盤(pán)頁(yè)數(shù)(如不是表,則為0)
* tuples - number of tuples in relation (not considering restrictions)
* 關(guān)系的元組數(shù)統(tǒng)計(jì)(還沒(méi)有考慮約束條件)
* allvisfrac - fraction of disk pages that are marked all-visible
* 標(biāo)記為all-visible的磁盤(pán)頁(yè)數(shù)比例
* subroot - PlannerInfo for subquery (NULL if it's not a subquery)
* 用于子查詢(xún)的PlannerInfo(如果不是子查詢(xún)呻疹,則為NULL)
* subplan_params - list of PlannerParamItems to be passed to subquery
* 要傳遞給子查詢(xún)的PlannerParamItems的鏈表
* Note: for a subquery, tuples and subroot are not set immediately
* upon creation of the RelOptInfo object; they are filled in when
* set_subquery_pathlist processes the object.
* 對(duì)于子查詢(xún)吃引,元組和subroot不會(huì)在創(chuàng)建RelOptInfo對(duì)象時(shí)立即設(shè)置;
* 它們是在set_subquery_pathlist處理對(duì)象時(shí)填充的。
*
* For otherrels that are appendrel members, these fields are filled
* in just as for a baserel, except we don't bother with lateral_vars.
* 對(duì)于其他appendrel成員刽锤,這些字段就像base rels一樣被填充镊尺,
* 除了我們不關(guān)心的lateral_vars。
*
* If the relation is either a foreign table or a join of foreign tables that
* all belong to the same foreign server and are assigned to the same user to
* check access permissions as (cf checkAsUser), these fields will be set:
* 如果關(guān)系是一個(gè)外表或一個(gè)外表的連接并思,這些表都屬于相同的外服務(wù)器
* 并被分配給相同的用戶(hù)來(lái)檢查訪問(wèn)權(quán)限(cf checkAsUser)庐氮,這些字段將被設(shè)置:
*
* serverid - OID of foreign server, if foreign table (else InvalidOid)
* 外部服務(wù)器的OID,如不為外部表則為InvalidOid
* userid - OID of user to check access as (InvalidOid means current user)
* 檢查訪問(wèn)權(quán)限的用戶(hù)OID(InvalidOid表示當(dāng)前用戶(hù))
* useridiscurrent - we've assumed that userid equals current user
* 我們假設(shè)userid為當(dāng)前用戶(hù)
* fdwroutine - function hooks for FDW, if foreign table (else NULL)
* FDW的函數(shù)鉤子,如不是外部表則為NULL
* fdw_private - private state for FDW, if foreign table (else NULL)
* FDW的私有狀態(tài),不是外部表則為NULL
*
* Two fields are used to cache knowledge acquired during the join search
* about whether this rel is provably unique when being joined to given other
* relation(s), ie, it can have at most one row matching any given row from
* that join relation. Currently we only attempt such proofs, and thus only
* populate these fields, for base rels; but someday they might be used for
* join rels too:
* 下面的兩個(gè)字段用于緩存在連接搜索過(guò)程中獲取的信息宋彼,
* 這些信息是關(guān)于當(dāng)這個(gè)rel被連接到給定的其他關(guān)系時(shí)是否被證明是唯一的弄砍,
* 也就是說(shuō),它最多只能有一行匹配來(lái)自該連接關(guān)系的任何給定行输涕。
* 目前我們只嘗試這樣的證明音婶,因此只填充這些字段,用于base rels;
* 但總有一天它們也可以被用來(lái)加入join rels:
*
* unique_for_rels - list of Relid sets, each one being a set of other
* rels for which this one has been proven unique
* Relid集合的鏈表莱坎,每一個(gè)都是一組other rels,這些rels已經(jīng)被證明是唯一的
* non_unique_for_rels - list of Relid sets, each one being a set of
* other rels for which we have tried and failed to prove
* this one unique
* Relid集合的鏈表衣式,每個(gè)集合都是other rels,這些rels試圖證明唯一的檐什,但失敗了
*
* The presence of the following fields depends on the restrictions
* and joins that the relation participates in:
* 以下字段的存在取決于約束條件和關(guān)系所參與的連接:
*
* baserestrictinfo - List of RestrictInfo nodes, containing info about
* each non-join qualification clause in which this relation
* participates (only used for base rels)
* RestrictInfo節(jié)點(diǎn)鏈表碴卧,其中包含關(guān)于此關(guān)系參與的每個(gè)非連接限定子句的信息(僅用于基礎(chǔ)rels)
* baserestrictcost - Estimated cost of evaluating the baserestrictinfo
* clauses at a single tuple (only used for base rels)
* 在單個(gè)元組中解析baserestrictinfo子句的估算成本(僅用于基礎(chǔ)rels)
* baserestrict_min_security - Smallest security_level found among
* clauses in baserestrictinfo
* 在baserestrictinfo子句中找到的最小security_level
* joininfo - List of RestrictInfo nodes, containing info about each
* join clause in which this relation participates (but
* note this excludes clauses that might be derivable from
* EquivalenceClasses)
* RestrictInfo節(jié)點(diǎn)鏈表,其中包含關(guān)于此關(guān)系參與的每個(gè)連接條件子句的信息
* (但請(qǐng)注意乃正,這排除了可能從等價(jià)類(lèi)派生的子句)
* has_eclass_joins - flag that EquivalenceClass joins are possible
* 用于標(biāo)記等價(jià)類(lèi)連接是可能的
*
* Note: Keeping a restrictinfo list in the RelOptInfo is useful only for
* base rels, because for a join rel the set of clauses that are treated as
* restrict clauses varies depending on which sub-relations we choose to join.
* (For example, in a 3-base-rel join, a clause relating rels 1 and 2 must be
* treated as a restrictclause if we join {1} and {2 3} to make {1 2 3}; but
* if we join {1 2} and {3} then that clause will be a restrictclause in {1 2}
* and should not be processed again at the level of {1 2 3}.) Therefore,
* the restrictinfo list in the join case appears in individual JoinPaths
* (field joinrestrictinfo), not in the parent relation. But it's OK for
* the RelOptInfo to store the joininfo list, because that is the same
* for a given rel no matter how we form it.
* 注意:在RelOptInfo中保存一個(gè)restrictinfo鏈表只對(duì)基礎(chǔ)rels有用住册,
* 因?yàn)閷?duì)于一個(gè)join rel,被視為限制子句的子句集會(huì)根據(jù)我們選擇加入的子關(guān)系而變化烫葬。(例如界弧,在一個(gè)3-base-rel連接中凡蜻,如果我們加入{1}和{2 3}以生成{1 2 3},則與efs 1和2相關(guān)的子句必須被視為限制性子句;但是如果我們加入{1 2}和{3}垢箕,那么該子句將是{1 2}中的一個(gè)限制性子句划栓,不應(yīng)該在{1 2 3}的級(jí)別上再次處理)。因此条获,在join案例中忠荞,節(jié)流信息列表出現(xiàn)在單獨(dú)的連接路徑(字段join節(jié)流信息)中,而不是在父關(guān)系中帅掘。但是RelOptInfo可以存儲(chǔ)joininfo列表委煤,因?yàn)閷?duì)于給定的rel,無(wú)論我們?nèi)绾涡纬伤际且粯拥摹? *
* We store baserestrictcost in the RelOptInfo (for base relations) because
* we know we will need it at least once (to price the sequential scan)
* and may need it multiple times to price index scans.
* 我們將baserestrictcost存儲(chǔ)在RelOptInfo(用于基本關(guān)系)中修档,
* 因?yàn)槲覀冎乐辽傩枰淮?為順序掃描計(jì)算成本)碧绞,并且可能需要它多次來(lái)為索引掃描計(jì)算成本。
*
* If the relation is partitioned, these fields will be set:
* 如果關(guān)系是分區(qū)表,會(huì)設(shè)置這些字段:
*
* part_scheme - Partitioning scheme of the relation
* 關(guān)系的分區(qū)schema
* nparts - Number of partitions
* 關(guān)系的分區(qū)數(shù)
* boundinfo - Partition bounds
* 分區(qū)邊界信息
* partition_qual - Partition constraint if not the root
* 如非root,則該字段存儲(chǔ)分區(qū)約束條件
* part_rels - RelOptInfos for each partition
* 每個(gè)分區(qū)的RelOptInfos
* partexprs, nullable_partexprs - Partition key expressions
* 分區(qū)鍵表達(dá)式
* partitioned_child_rels - RT indexes of unpruned partitions of
* this relation that are partitioned tables
* themselves, in hierarchical order
* 關(guān)系中未修剪(unpruned)分區(qū)的RT索引吱窝,
* 這些分區(qū)本身就是分區(qū)表讥邻,按層次順序排列
*
* Note: A base relation always has only one set of partition keys, but a join
* relation may have as many sets of partition keys as the number of relations
* being joined. partexprs and nullable_partexprs are arrays containing
* part_scheme->partnatts elements each. Each of these elements is a list of
* partition key expressions. For a base relation each list in partexprs
* contains only one expression and nullable_partexprs is not populated. For a
* join relation, partexprs and nullable_partexprs contain partition key
* expressions from non-nullable and nullable relations resp. Lists at any
* given position in those arrays together contain as many elements as the
* number of joining relations.
* 注意:一個(gè)基本關(guān)系總是只有一組分區(qū)鍵,
* 但是連接關(guān)系的分區(qū)鍵可能與被連接的關(guān)系的數(shù)量一樣多院峡。
* partexprs和nullable_partexp是分別包含part_scheme->partnatts元素的數(shù)組兴使。
* 每個(gè)元素都是分區(qū)鍵表達(dá)式的鏈表。
* 對(duì)于基本關(guān)系照激,partexprs中的每個(gè)鏈表只包含一個(gè)表達(dá)式发魄,
* 并且不填充nullable_partexprs。
* 對(duì)于連接關(guān)系俩垃,partexprs和nullable_partexprs包含來(lái)自非空和可空關(guān)系resp的分區(qū)鍵表達(dá)式励幼。
* 這些數(shù)組中任意給定位置的鏈表包含的元素與連接關(guān)系的數(shù)量一樣多。
*----------
*/
typedef enum RelOptKind
{
RELOPT_BASEREL,//基本關(guān)系(如基表/子查詢(xún)等)
RELOPT_JOINREL,//連接產(chǎn)生的關(guān)系,要注意的是通過(guò)連接等方式產(chǎn)生的結(jié)果亦可以視為關(guān)系
RELOPT_OTHER_MEMBER_REL,
RELOPT_OTHER_JOINREL,
RELOPT_UPPER_REL,//上層的關(guān)系
RELOPT_OTHER_UPPER_REL,
RELOPT_DEADREL
} RelOptKind;
/*
* Is the given relation a simple relation i.e a base or "other" member
* relation?
*/
#define IS_SIMPLE_REL(rel) \
((rel)->reloptkind == RELOPT_BASEREL || \
(rel)->reloptkind == RELOPT_OTHER_MEMBER_REL)
/* Is the given relation a join relation? */
#define IS_JOIN_REL(rel) \
((rel)->reloptkind == RELOPT_JOINREL || \
(rel)->reloptkind == RELOPT_OTHER_JOINREL)
/* Is the given relation an upper relation? */
#define IS_UPPER_REL(rel) \
((rel)->reloptkind == RELOPT_UPPER_REL || \
(rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
/* Is the given relation an "other" relation? */
#define IS_OTHER_REL(rel) \
((rel)->reloptkind == RELOPT_OTHER_MEMBER_REL || \
(rel)->reloptkind == RELOPT_OTHER_JOINREL || \
(rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
typedef struct RelOptInfo
{
//節(jié)點(diǎn)標(biāo)識(shí)
NodeTag type;
//RelOpt類(lèi)型
RelOptKind reloptkind;
/* all relations included in this RelOptInfo */
//所有關(guān)系都有的屬性
//Relids(rtindex)集合
Relids relids; /* set of base relids (rangetable indexes) */
/* size estimates generated by planner */
//規(guī)劃器生成的大小估算
//結(jié)果元組的估算數(shù)量
double rows; /* estimated number of result tuples */
/* per-relation planner control flags */
//規(guī)劃器使用的每個(gè)關(guān)系的控制標(biāo)記
//是否考慮啟動(dòng)成本?是,需要保留啟動(dòng)成本低的路徑
bool consider_startup; /* keep cheap-startup-cost paths? */
//是否考慮參數(shù)化?的路徑
bool consider_param_startup; /* ditto for parameterized paths? */
//是否考慮并行處理路徑
bool consider_parallel; /* consider parallel paths? */
/* default result targetlist for Paths scanning this relation */
//掃描該Relation時(shí)默認(rèn)的結(jié)果投影列
//Vars/Exprs,成本,行平均大小鏈表
struct PathTarget *reltarget; /* list of Vars/Exprs, cost, width */
/* materialization information */
//物化信息
//訪問(wèn)路徑鏈表
List *pathlist; /* Path structures */
//路徑鏈表中的ParamPathInfos鏈表
List *ppilist; /* ParamPathInfos used in pathlist */
//并行部分路徑
List *partial_pathlist; /* partial Paths */
//啟動(dòng)代價(jià)最低的路徑
struct Path *cheapest_startup_path;
//整體代價(jià)最低的路徑
struct Path *cheapest_total_path;
//獲取唯一值代價(jià)最低的路徑
struct Path *cheapest_unique_path;
//參數(shù)化代價(jià)最低的路徑
List *cheapest_parameterized_paths;
/* parameterization information needed for both base rels and join rels */
/* (see also lateral_vars and lateral_referencers) */
//基本通道和連接通道都需要參數(shù)化信息
//(參考lateral_vars和lateral_referencers)
//使用lateral語(yǔ)法,需依賴(lài)的Relids
Relids direct_lateral_relids; /* rels directly laterally referenced */
//rel的最小化參數(shù)信息
Relids lateral_relids; /* minimum parameterization of rel */
/* information about a base rel (not set for join rels!) */
//reloptkind=RELOPT_BASEREL時(shí)使用的數(shù)據(jù)結(jié)構(gòu)
//relid
Index relid; /* Relation ID */
//表空間
Oid reltablespace; /* containing tablespace */
//類(lèi)型:基表?子查詢(xún)?還是函數(shù)等等?
RTEKind rtekind; /* RELATION, SUBQUERY, FUNCTION, etc */
//最小的屬性編號(hào)
AttrNumber min_attr; /* smallest attrno of rel (often <0) */
//最大的屬性編號(hào)
AttrNumber max_attr; /* largest attrno of rel */
//屬性數(shù)組
Relids *attr_needed; /* array indexed [min_attr .. max_attr] */
//屬性寬度
int32 *attr_widths; /* array indexed [min_attr .. max_attr] */
//關(guān)系依賴(lài)的LATERAL Vars/PHVs
List *lateral_vars; /* LATERAL Vars and PHVs referenced by rel */
//依賴(lài)該關(guān)系的Relids
Relids lateral_referencers; /* rels that reference me laterally */
//該關(guān)系的IndexOptInfo鏈表
List *indexlist; /* list of IndexOptInfo */
//統(tǒng)計(jì)信息鏈表
List *statlist; /* list of StatisticExtInfo */
//塊數(shù)
BlockNumber pages; /* size estimates derived from pg_class */
//元組數(shù)
double tuples; /* */
//
double allvisfrac; /* ? */
//如為子查詢(xún),存儲(chǔ)子查詢(xún)的root
PlannerInfo *subroot; /* if subquery */
//如為子查詢(xún),存儲(chǔ)子查詢(xún)的參數(shù)
List *subplan_params; /* if subquery */
//并行執(zhí)行,需要多少個(gè)workers?
int rel_parallel_workers; /* wanted number of parallel workers */
/* Information about foreign tables and foreign joins */
//FWD相關(guān)信息
//表或連接的服務(wù)器標(biāo)識(shí)符
Oid serverid; /* identifies server for the table or join */
//用戶(hù)id標(biāo)識(shí)
Oid userid; /* identifies user to check access as */
//對(duì)于當(dāng)前用戶(hù)來(lái)說(shuō),連接才是有效的
bool useridiscurrent; /* join is only valid for current user */
/* use "struct FdwRoutine" to avoid including fdwapi.h here */
//使用結(jié)構(gòu)體FdwRoutine,避免包含頭文件fdwapi.h
struct FdwRoutine *fdwroutine;
void *fdw_private;
/* cache space for remembering if we have proven this relation unique */
//如果已證明該關(guān)系是唯一的,那么這些是用于緩存這些信息的字段
//已知的,可保證唯一的Relids鏈表
List *unique_for_rels; /* known unique for these other relid
* set(s) */
//已知的,不唯一的Relids鏈表
List *non_unique_for_rels; /* known not unique for these set(s) */
/* used by various scans and joins: */
//用于各種掃描和連接
//如為基本關(guān)系,存儲(chǔ)約束條件鏈表
List *baserestrictinfo; /* RestrictInfo structures (if base rel) */
//解析約束表達(dá)式的成本?
QualCost baserestrictcost; /* cost of evaluating the above */
//最低安全等級(jí)
Index baserestrict_min_security; /* min security_level found in
* baserestrictinfo */
//連接語(yǔ)句的約束條件信息
List *joininfo; /* RestrictInfo structures for join clauses
* involving this rel */
//是否存在等價(jià)類(lèi)連接?
bool has_eclass_joins; /* T means joininfo is incomplete */
/* used by partitionwise joins: */
//partitionwise連接使用的字段
//是否考慮使用partitionwise join?
bool consider_partitionwise_join; /* consider partitionwise
* join paths? (if
* partitioned rel) */
//最高層的父關(guān)系Relids
Relids top_parent_relids; /* Relids of topmost parents (if "other"
* rel) */
/* used for partitioned relations */
//分區(qū)表使用
//分區(qū)的schema
PartitionScheme part_scheme; /* Partitioning scheme. */
//分區(qū)數(shù)
int nparts; /* number of partitions */
//分區(qū)邊界信息
struct PartitionBoundInfoData *boundinfo; /* Partition bounds */
//分區(qū)約束
List *partition_qual; /* partition constraint */
//分區(qū)的RelOptInfo數(shù)組
struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions,
* stored in the same order of bounds */
//非空分區(qū)鍵表達(dá)式鏈表
List **partexprs; /* Non-nullable partition key expressions. */
//可為空的分區(qū)鍵表達(dá)式
List **nullable_partexprs; /* Nullable partition key expressions. */
// 分區(qū)子表RT Indexes鏈表
List *partitioned_child_rels; /*List of RT indexes. */
} RelOptInfo;
AppendRelInfo
Append-relation信息.
當(dāng)我們將可繼承表(分區(qū)表)或UNION-ALL子查詢(xún)展開(kāi)為“追加關(guān)系”(本質(zhì)上是子RTE的鏈表)時(shí)吆寨,為每個(gè)子RTE構(gòu)建一個(gè)AppendRelInfo赏淌。
AppendRelInfos鏈表指示在展開(kāi)父節(jié)點(diǎn)時(shí)必須包含哪些子rte,每個(gè)節(jié)點(diǎn)具有將引用父節(jié)點(diǎn)的Vars轉(zhuǎn)換為引用該子節(jié)點(diǎn)的Vars所需的所有信息啄清。
/*
* Append-relation info.
* Append-relation信息.
*
* When we expand an inheritable table or a UNION-ALL subselect into an
* "append relation" (essentially, a list of child RTEs), we build an
* AppendRelInfo for each child RTE. The list of AppendRelInfos indicates
* which child RTEs must be included when expanding the parent, and each node
* carries information needed to translate Vars referencing the parent into
* Vars referencing that child.
* 當(dāng)我們將可繼承表(分區(qū)表)或UNION-ALL子查詢(xún)展開(kāi)為“追加關(guān)系”(本質(zhì)上是子RTE的鏈表)時(shí),
* 為每個(gè)子RTE構(gòu)建一個(gè)AppendRelInfo俺孙。
* AppendRelInfos鏈表指示在展開(kāi)父節(jié)點(diǎn)時(shí)必須包含哪些子rte辣卒,
* 每個(gè)節(jié)點(diǎn)具有將引用父節(jié)點(diǎn)的Vars轉(zhuǎn)換為引用該子節(jié)點(diǎn)的Vars所需的所有信息。
*
* These structs are kept in the PlannerInfo node's append_rel_list.
* Note that we just throw all the structs into one list, and scan the
* whole list when desiring to expand any one parent. We could have used
* a more complex data structure (eg, one list per parent), but this would
* be harder to update during operations such as pulling up subqueries,
* and not really any easier to scan. Considering that typical queries
* will not have many different append parents, it doesn't seem worthwhile
* to complicate things.
* 這些結(jié)構(gòu)體保存在PlannerInfo節(jié)點(diǎn)的append_rel_list中睛榄。
* 注意,只是將所有的結(jié)構(gòu)體放入一個(gè)鏈表中,并在希望展開(kāi)任何父類(lèi)時(shí)掃描整個(gè)鏈表檀葛。
* 本可以使用更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(例如忠怖,每個(gè)父節(jié)點(diǎn)一個(gè)列表)港准,
* 但是在提取子查詢(xún)之類(lèi)的操作中更新它會(huì)更困難,
* 而且實(shí)際上也不會(huì)更容易掃描咧欣。
* 考慮到典型的查詢(xún)不會(huì)有很多不同的附加項(xiàng)浅缸,因此似乎不值得將事情復(fù)雜化。
*
* Note: after completion of the planner prep phase, any given RTE is an
* append parent having entries in append_rel_list if and only if its
* "inh" flag is set. We clear "inh" for plain tables that turn out not
* to have inheritance children, and (in an abuse of the original meaning
* of the flag) we set "inh" for subquery RTEs that turn out to be
* flattenable UNION ALL queries. This lets us avoid useless searches
* of append_rel_list.
* 注意:計(jì)劃準(zhǔn)備階段完成后,
* 當(dāng)且僅當(dāng)它的“inh”標(biāo)志已設(shè)置時(shí),給定的RTE是一個(gè)append parent在append_rel_list中的一個(gè)條目魄咕。
* 我們?yōu)闆](méi)有child的平面表清除“inh”標(biāo)記,
* 同時(shí)(有濫用標(biāo)記的嫌疑)為UNION ALL查詢(xún)中的子查詢(xún)RTEs設(shè)置“inh”標(biāo)記衩椒。
* 這樣可以避免對(duì)append_rel_list進(jìn)行無(wú)用的搜索。
*
* Note: the data structure assumes that append-rel members are single
* baserels. This is OK for inheritance, but it prevents us from pulling
* up a UNION ALL member subquery if it contains a join. While that could
* be fixed with a more complex data structure, at present there's not much
* point because no improvement in the plan could result.
* 注意:數(shù)據(jù)結(jié)構(gòu)假定附加的rel成員是獨(dú)立的baserels哮兰。
* 這對(duì)于繼承來(lái)說(shuō)是可以的毛萌,但是如果UNION ALL member子查詢(xún)包含一個(gè)join,
* 那么它將阻止我們提取UNION ALL member子查詢(xún)喝滞。
* 雖然可以用更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)解決這個(gè)問(wèn)題阁将,但目前沒(méi)有太大意義,因?yàn)樵撚?jì)劃可能不會(huì)有任何改進(jìn)右遭。
*/
typedef struct AppendRelInfo
{
NodeTag type;
/*
* These fields uniquely identify this append relationship. There can be
* (in fact, always should be) multiple AppendRelInfos for the same
* parent_relid, but never more than one per child_relid, since a given
* RTE cannot be a child of more than one append parent.
* 這些字段惟一地標(biāo)識(shí)這個(gè)append relationship做盅。
* 對(duì)于同一個(gè)parent_relid可以有(實(shí)際上應(yīng)該總是)多個(gè)AppendRelInfos,
* 但是每個(gè)child_relid不能有多個(gè)AppendRelInfos狸演,
* 因?yàn)榻o定的RTE不能是多個(gè)append parent的子節(jié)點(diǎn)言蛇。
*/
Index parent_relid; /* parent rel的RT索引;RT index of append parent rel */
Index child_relid; /* child rel的RT索引;RT index of append child rel */
/*
* For an inheritance appendrel, the parent and child are both regular
* relations, and we store their rowtype OIDs here for use in translating
* whole-row Vars. For a UNION-ALL appendrel, the parent and child are
* both subqueries with no named rowtype, and we store InvalidOid here.
* 對(duì)于繼承appendrel,父類(lèi)和子類(lèi)都是普通關(guān)系宵距,
* 我們將它們的rowtype OIDs存儲(chǔ)在這里腊尚,用于轉(zhuǎn)換whole-row Vars。
* 對(duì)于UNION-ALL appendrel满哪,父查詢(xún)和子查詢(xún)都是沒(méi)有指定行類(lèi)型的子查詢(xún)婿斥,
* 我們?cè)谶@里存儲(chǔ)InvalidOid。
*/
Oid parent_reltype; /* OID of parent's composite type */
Oid child_reltype; /* OID of child's composite type */
/*
* The N'th element of this list is a Var or expression representing the
* child column corresponding to the N'th column of the parent. This is
* used to translate Vars referencing the parent rel into references to
* the child. A list element is NULL if it corresponds to a dropped
* column of the parent (this is only possible for inheritance cases, not
* UNION ALL). The list elements are always simple Vars for inheritance
* cases, but can be arbitrary expressions in UNION ALL cases.
* 這個(gè)列表的第N個(gè)元素是一個(gè)Var或表達(dá)式哨鸭,表示與父元素的第N列對(duì)應(yīng)的子列民宿。
* 這用于將引用parent rel的Vars轉(zhuǎn)換為對(duì)子rel的引用。
* 如果鏈表元素與父元素的已刪除列相對(duì)應(yīng)像鸡,則該元素為NULL
* (這只適用于繼承情況活鹰,而不是UNION ALL)。
* 對(duì)于繼承情況只估,鏈表元素總是簡(jiǎn)單的變量志群,但是可以是UNION ALL情況下的任意表達(dá)式。
*
* Notice we only store entries for user columns (attno > 0). Whole-row
* Vars are special-cased, and system columns (attno < 0) need no special
* translation since their attnos are the same for all tables.
* 注意蛔钙,我們只存儲(chǔ)用戶(hù)列的條目(attno > 0)锌云。
* Whole-row Vars是大小寫(xiě)敏感的,系統(tǒng)列(attno < 0)不需要特別的轉(zhuǎn)換吁脱,
* 因?yàn)樗鼈兊腶ttno對(duì)所有表都是相同的桑涎。
*
* Caution: the Vars have varlevelsup = 0. Be careful to adjust as needed
* when copying into a subquery.
* 注意:Vars的varlevelsup = 0彬向。
* 在將數(shù)據(jù)復(fù)制到子查詢(xún)時(shí),要注意根據(jù)需要進(jìn)行調(diào)整攻冷。
*/
//child's Vars中的表達(dá)式
List *translated_vars; /* Expressions in the child's Vars */
/*
* We store the parent table's OID here for inheritance, or InvalidOid for
* UNION ALL. This is only needed to help in generating error messages if
* an attempt is made to reference a dropped parent column.
* 我們將父表的OID存儲(chǔ)在這里用于繼承娃胆,
* 如為UNION ALL,則這里存儲(chǔ)的是InvalidOid。
* 只有在試圖引用已刪除的父列時(shí)讲衫,才需要這樣做來(lái)幫助生成錯(cuò)誤消息缕棵。
*/
Oid parent_reloid; /* OID of parent relation */
} AppendRelInfo;
PlannerInfo
該數(shù)據(jù)結(jié)構(gòu)用于存儲(chǔ)查詢(xún)語(yǔ)句在規(guī)劃/優(yōu)化過(guò)程中的相關(guān)信息
/*----------
* PlannerInfo
* Per-query information for planning/optimization
* 用于規(guī)劃/優(yōu)化的每個(gè)查詢(xún)信息
*
* This struct is conventionally called "root" in all the planner routines.
* It holds links to all of the planner's working state, in addition to the
* original Query. Note that at present the planner extensively modifies
* the passed-in Query data structure; someday that should stop.
* 在所有計(jì)劃程序例程中,這個(gè)結(jié)構(gòu)通常稱(chēng)為“root”涉兽。
* 除了原始查詢(xún)之外招驴,它還保存到所有計(jì)劃器工作狀態(tài)的鏈接。
* 注意枷畏,目前計(jì)劃器會(huì)毫無(wú)節(jié)制的修改傳入的查詢(xún)數(shù)據(jù)結(jié)構(gòu),相信總有一天這種情況會(huì)停止的别厘。
*----------
*/
struct AppendRelInfo;
typedef struct PlannerInfo
{
NodeTag type;//Node標(biāo)識(shí)
//查詢(xún)樹(shù)
Query *parse; /* the Query being planned */
//當(dāng)前的planner全局信息
PlannerGlobal *glob; /* global info for current planner run */
//查詢(xún)層次,1標(biāo)識(shí)最高層
Index query_level; /* 1 at the outermost Query */
// 如為子計(jì)劃,則這里存儲(chǔ)父計(jì)劃器指針,NULL標(biāo)識(shí)最高層
struct PlannerInfo *parent_root; /* NULL at outermost Query */
/*
* plan_params contains the expressions that this query level needs to
* make available to a lower query level that is currently being planned.
* outer_params contains the paramIds of PARAM_EXEC Params that outer
* query levels will make available to this query level.
* plan_params包含該查詢(xún)級(jí)別需要提供給當(dāng)前計(jì)劃的較低查詢(xún)級(jí)別的表達(dá)式。
* outer_params包含PARAM_EXEC Params的參數(shù)拥诡,外部查詢(xún)級(jí)別將使該查詢(xún)級(jí)別可用這些參數(shù)触趴。
*/
List *plan_params; /* list of PlannerParamItems, see below */
Bitmapset *outer_params;
/*
* simple_rel_array holds pointers to "base rels" and "other rels" (see
* comments for RelOptInfo for more info). It is indexed by rangetable
* index (so entry 0 is always wasted). Entries can be NULL when an RTE
* does not correspond to a base relation, such as a join RTE or an
* unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
* simple_rel_array保存指向“base rels”和“other rels”的指針
* (有關(guān)RelOptInfo的更多信息,請(qǐng)參見(jiàn)注釋)渴肉。
* 它由可范圍表索引建立索引(因此條目0總是被浪費(fèi))冗懦。
* 當(dāng)RTE與基本關(guān)系(如JOIN RTE或未被引用的視圖RTE時(shí))不相對(duì)應(yīng)
* 或者如果RelOptInfo還沒(méi)有生成,條目可以為NULL仇祭。
*/
//RelOptInfo數(shù)組,存儲(chǔ)"base rels",比如基表/子查詢(xún)等.
//該數(shù)組與RTE的順序一一對(duì)應(yīng),而且是從1開(kāi)始,因此[0]無(wú)用 */
struct RelOptInfo **simple_rel_array; /* All 1-rel RelOptInfos */
int simple_rel_array_size; /* 數(shù)組大小,allocated size of array */
/*
* simple_rte_array is the same length as simple_rel_array and holds
* pointers to the associated rangetable entries. This lets us avoid
* rt_fetch(), which can be a bit slow once large inheritance sets have
* been expanded.
* simple_rte_array的長(zhǎng)度與simple_rel_array相同披蕉,
* 并保存指向相應(yīng)范圍表?xiàng)l目的指針。
* 這使我們可以避免執(zhí)行rt_fetch()乌奇,因?yàn)橐坏U(kuò)展了大型繼承集没讲,rt_fetch()可能會(huì)有點(diǎn)慢。
*/
//RTE數(shù)組
RangeTblEntry **simple_rte_array; /* rangetable as an array */
/*
* append_rel_array is the same length as the above arrays, and holds
* pointers to the corresponding AppendRelInfo entry indexed by
* child_relid, or NULL if none. The array itself is not allocated if
* append_rel_list is empty.
* append_rel_array與上述數(shù)組的長(zhǎng)度相同礁苗,
* 并保存指向?qū)?yīng)的AppendRelInfo條目的指針爬凑,該條目由child_relid索引,
* 如果沒(méi)有索引則為NULL试伙。
* 如果append_rel_list為空嘁信,則不分配數(shù)組本身。
*/
//處理集合操作如UNION ALL時(shí)使用和分區(qū)表時(shí)使用
struct AppendRelInfo **append_rel_array;
/*
* all_baserels is a Relids set of all base relids (but not "other"
* relids) in the query; that is, the Relids identifier of the final join
* we need to form. This is computed in make_one_rel, just before we
* start making Paths.
* all_baserels是查詢(xún)中所有base relids(但不是“other” relids)的一個(gè)Relids集合;
* 也就是說(shuō)疏叨,這是需要形成的最終連接的Relids標(biāo)識(shí)符吱抚。
* 這是在開(kāi)始創(chuàng)建路徑之前在make_one_rel中計(jì)算的。
*/
Relids all_baserels;//"base rels"
/*
* nullable_baserels is a Relids set of base relids that are nullable by
* some outer join in the jointree; these are rels that are potentially
* nullable below the WHERE clause, SELECT targetlist, etc. This is
* computed in deconstruct_jointree.
* nullable_baserels是由jointree中的某些外連接中值可為空的base Relids集合;
* 這些是在WHERE子句考廉、SELECT targetlist等下面可能為空的樹(shù)。
* 這是在deconstruct_jointree中處理獲得的携御。
*/
//Nullable-side端的"base rels"
Relids nullable_baserels;
/*
* join_rel_list is a list of all join-relation RelOptInfos we have
* considered in this planning run. For small problems we just scan the
* list to do lookups, but when there are many join relations we build a
* hash table for faster lookups. The hash table is present and valid
* when join_rel_hash is not NULL. Note that we still maintain the list
* even when using the hash table for lookups; this simplifies life for
* GEQO.
* join_rel_list是在計(jì)劃執(zhí)行中考慮的所有連接關(guān)系RelOptInfos的鏈表昌粤。
* 對(duì)于小問(wèn)題既绕,只需要掃描鏈表執(zhí)行查找,但是當(dāng)存在許多連接關(guān)系時(shí)涮坐,
* 需要構(gòu)建一個(gè)散列表來(lái)進(jìn)行更快的查找凄贩。
* 當(dāng)join_rel_hash不為空時(shí),哈希表是有效可用于查詢(xún)的袱讹。
* 注意疲扎,即使在使用哈希表進(jìn)行查找時(shí),仍然維護(hù)該鏈表;這簡(jiǎn)化了GEQO(遺傳算法)的生命周期捷雕。
*/
//參與連接的Relation的RelOptInfo鏈表
List *join_rel_list; /* list of join-relation RelOptInfos */
//可加快鏈表訪問(wèn)的hash表
struct HTAB *join_rel_hash; /* optional hashtable for join relations */
/*
* When doing a dynamic-programming-style join search, join_rel_level[k]
* is a list of all join-relation RelOptInfos of level k, and
* join_cur_level is the current level. New join-relation RelOptInfos are
* automatically added to the join_rel_level[join_cur_level] list.
* join_rel_level is NULL if not in use.
* 在執(zhí)行動(dòng)態(tài)規(guī)劃算法的連接搜索時(shí)椒丧,join_rel_level[k]是k級(jí)的所有連接關(guān)系RelOptInfos的列表,
* join_cur_level是當(dāng)前級(jí)別救巷。
* 新的連接關(guān)系RelOptInfos會(huì)自動(dòng)添加到j(luò)oin_rel_level[join_cur_level]鏈表中壶熏。
* 如果不使用join_rel_level,則為NULL浦译。
*/
//RelOptInfo指針鏈表數(shù)組,k層的join存儲(chǔ)在[k]中
List **join_rel_level; /* lists of join-relation RelOptInfos */
//當(dāng)前的join層次
int join_cur_level; /* index of list being extended */
//查詢(xún)的初始化計(jì)劃鏈表
List *init_plans; /* init SubPlans for query */
//CTE子計(jì)劃ID鏈表
List *cte_plan_ids; /* per-CTE-item list of subplan IDs */
//MULTIEXPR子查詢(xún)輸出的參數(shù)鏈表的鏈表
List *multiexpr_params; /* List of Lists of Params for MULTIEXPR
* subquery outputs */
//活動(dòng)的等價(jià)類(lèi)鏈表
List *eq_classes; /* list of active EquivalenceClasses */
//規(guī)范化的PathKey鏈表
List *canon_pathkeys; /* list of "canonical" PathKeys */
//外連接約束條件鏈表(左)
List *left_join_clauses; /* list of RestrictInfos for mergejoinable
* outer join clauses w/nonnullable var on
* left */
//外連接約束條件鏈表(右)
List *right_join_clauses; /* list of RestrictInfos for mergejoinable
* outer join clauses w/nonnullable var on
* right */
//全連接約束條件鏈表
List *full_join_clauses; /* list of RestrictInfos for mergejoinable
* full join clauses */
//特殊連接信息鏈表
List *join_info_list; /* list of SpecialJoinInfos */
//AppendRelInfo鏈表
List *append_rel_list; /* list of AppendRelInfos */
//PlanRowMarks鏈表
List *rowMarks; /* list of PlanRowMarks */
//PHI鏈表
List *placeholder_list; /* list of PlaceHolderInfos */
// 外鍵信息鏈表
List *fkey_list; /* list of ForeignKeyOptInfos */
//query_planner()要求的PathKeys鏈表
List *query_pathkeys; /* desired pathkeys for query_planner() */
//分組子句路徑鍵
List *group_pathkeys; /* groupClause pathkeys, if any */
//窗口函數(shù)路徑鍵
List *window_pathkeys; /* pathkeys of bottom window, if any */
//distinctClause路徑鍵
List *distinct_pathkeys; /* distinctClause pathkeys, if any */
//排序路徑鍵
List *sort_pathkeys; /* sortClause pathkeys, if any */
//已規(guī)范化的分區(qū)Schema
List *part_schemes; /* Canonicalised partition schemes used in the
* query. */
//嘗試連接的RelOptInfo鏈表
List *initial_rels; /* RelOptInfos we are now trying to join */
/* Use fetch_upper_rel() to get any particular upper rel */
//上層的RelOptInfo鏈表
List *upper_rels[UPPERREL_FINAL + 1]; /* upper-rel RelOptInfos */
/* Result tlists chosen by grouping_planner for upper-stage processing */
//grouping_planner為上層處理選擇的結(jié)果tlists
struct PathTarget *upper_targets[UPPERREL_FINAL + 1];//
/*
* grouping_planner passes back its final processed targetlist here, for
* use in relabeling the topmost tlist of the finished Plan.
* grouping_planner在這里傳回它最終處理過(guò)的targetlist棒假,用于重新標(biāo)記已完成計(jì)劃的最頂層tlist。
*/
////最后需處理的投影列
List *processed_tlist;
/* Fields filled during create_plan() for use in setrefs.c */
//setrefs.c中在create_plan()函數(shù)調(diào)用期間填充的字段
//分組函數(shù)屬性映射
AttrNumber *grouping_map; /* for GroupingFunc fixup */
//MinMaxAggInfos鏈表
List *minmax_aggs; /* List of MinMaxAggInfos */
//內(nèi)存上下文
MemoryContext planner_cxt; /* context holding PlannerInfo */
//關(guān)系的page計(jì)數(shù)
double total_table_pages; /* # of pages in all tables of query */
//query_planner輸入?yún)?shù):元組處理比例
double tuple_fraction; /* tuple_fraction passed to query_planner */
//query_planner輸入?yún)?shù):limit_tuple
double limit_tuples; /* limit_tuples passed to query_planner */
//表達(dá)式的最小安全等級(jí)
Index qual_security_level; /* minimum security_level for quals */
/* Note: qual_security_level is zero if there are no securityQuals */
//注意:如果沒(méi)有securityQuals, 則qual_security_level是NULL(0)
//如目標(biāo)relation是分區(qū)表的child/partition/分區(qū)表,則通過(guò)此字段標(biāo)記
InheritanceKind inhTargetKind; /* indicates if the target relation is an
* inheritance child or partition or a
* partitioned table */
//是否存在RTE_JOIN的RTE
bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
//是否存在標(biāo)記為L(zhǎng)ATERAL的RTE
bool hasLateralRTEs; /* true if any RTEs are marked LATERAL */
//是否存在已在jointree刪除的RTE
bool hasDeletedRTEs; /* true if any RTE was deleted from jointree */
//是否存在Having子句
bool hasHavingQual; /* true if havingQual was non-null */
//如約束條件中存在pseudoconstant = true,則此字段為T(mén)
bool hasPseudoConstantQuals; /* true if any RestrictInfo has
* pseudoconstant = true */
//是否存在遞歸語(yǔ)句
bool hasRecursion; /* true if planning a recursive WITH item */
/* These fields are used only when hasRecursion is true: */
//這些字段僅在hasRecursion為T(mén)時(shí)使用:
//工作表的PARAM_EXEC ID
int wt_param_id; /* PARAM_EXEC ID for the work table */
//非遞歸模式的訪問(wèn)路徑
struct Path *non_recursive_path; /* a path for non-recursive term */
/* These fields are workspace for createplan.c */
//這些字段用于createplan.c
//當(dāng)前節(jié)點(diǎn)之上的外部rels
Relids curOuterRels; /* outer rels above current node */
//未賦值的NestLoopParams參數(shù)
List *curOuterParams; /* not-yet-assigned NestLoopParams */
/* optional private data for join_search_hook, e.g., GEQO */
//可選的join_search_hook私有數(shù)據(jù)精盅,例如GEQO
void *join_search_private;
/* Does this query modify any partition key columns? */
//該查詢(xún)是否更新分區(qū)鍵列?
bool partColsUpdated;
} PlannerInfo;
二帽哑、參考資料
Parallel Append implementation
Partition Elimination in PostgreSQL 11