您好,登錄后才能下訂單哦!
本篇內容介紹了“PostgreSQL中分區表查詢相關的重要數據結構有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
RelOptInfo
RelOptInfo是規劃器/優化器使用的關系信息結構體
在規劃過程中已存在的基表或者是在關系運算過程中產生的中間關系或者是最終產生的關系,都使用RelOptInfo結構體進行封裝表示.
查詢分區表時該結構體中的part_scheme存儲分區的schema,nparts存儲分區數,boundinfo是分區邊界信息,partition_qual是分區約束條件,part_rels是分區表中每個分區的每個分區的RelOptInfo,partexprs是分區鍵表達式,partitioned_child_rels是關系中未修剪(unpruned)分區的RT索引.unpruned是指查詢分區表時,涉及的相關分區,比如 where c1 = 1 OR c1 = 2涉及的分區只有t_hash_partition_1和t_hash_partition_3,則在partitioned_child_rels中只有這兩個分區的信息.
如何pruned,下節介紹
/*---------- * RelOptInfo * Per-relation information for planning/optimization * 規劃器/優化器使用的關系信息結構體 * * 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. * 出于計劃目的,“base rel”要么是一個普通關系(表), * 要么是出現在范圍表中的子查詢或函數的輸出。 * 在這兩種情況下,它都是由RT索引惟一標識的。 * "joinrel"是兩個或兩個以上的base rels連接。 * 一個joinrel是由它的baserels的RT索引集標識。 * 我們為每個baserel和joinrel分別創建RelOptInfo節點, * 并將它們分別存儲在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. * 請注意,對于任何給定的base rels,無論我們以何種順序組合它們, * 都只有一個連接件;因此,一個無序的集合正好是標識它的數據類型。 * * 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.) * 同時存在“other rels”,類似于base rels,它們同樣都指向單個RT索引; * 但是它們不是join樹的一部分,并且被賦予不同的RelOptKind來標識它們。 * 目前唯一的其他類型是那些為“append relation”的成員關系而創建的, * 即繼承集或UNION ALL子查詢。 * 一個append relation有一個父RTE,它是一個基礎rel,表示整個append relation。 * 其他成員RTEs是otherrel.。 * 父節點存在于查詢的連接樹中,但成員無需存儲在連接樹中。 * 成員RTEs和otherrels用于計劃對append set的單表或子查詢的掃描; * 然后給出parent base rel的APPEND路徑和/或MergeAppend路徑,這些路徑包含單個成員rels的最佳路徑。 * (更多信息請參見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. * 曾經,還制作了其他的樹來表示連接rte,用于處理連接別名Vars。 * 目前不需要這樣做,因為在preprocess_expression期間,所有連接別名Vars都被擴展為非別名形式。 * * 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. * 還有表示不同分區表的子關系之間的連接的關系。 * 這些關系不會添加到join_rel_level鏈表中,因為動態規劃算法不會直接連接它們。 * * 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”關系, * 即描述掃描/連接后處理步驟(如聚合)的RelOptInfos。 * 這些RelOptInfos中的許多字段都是沒有意義的, * 但是它們的Path字段總是包含顯示執行該處理步驟的路徑。 * * Lastly, there is a RelOptKind for "dead" relations, which are base rels * that we have proven we don't need to join after all. * 最后,還有一種關系是“DEAD”的關系,在規劃期間已經證明不需要把此關系加入連接。 * * Parts of this data structure are specific to various scan and join * mechanisms. It didn't seem worth creating new node types for them. * 該數據結構的某些部分特定于各種掃描和連接機制。 * 但似乎不值得為它們創建新的節點類型。 * * relids - Set of base-relation identifiers; it is a base relation * if there is just one, a join relation if more than one * relids - 基礎關系標識符的集合;如只有一個則為基礎關系, * 如有多個則為連接關系 * rows - estimated number of tuples in the relation after restriction * clauses have been applied (ie, output rows of a plan for it) * rows - 應用約束條件子句后關系中元組的估算數目(即計劃的輸出行數) * 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 - 如果在具有低啟動成本的基礎上為這個rel保留訪問路徑有價值,則為真 * consider_param_startup - the same for parameterized paths * consider_param_startup - 與parameterized訪問路徑一致 * 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的默認路徑輸出投影列;通常會包含Var和PlaceHolderVar * pathlist - List of Path nodes, one for each potentially useful * method of generating the relation * 訪問路徑節點鏈表, 存儲每一種可能有用的生成關系的方法 * ppilist - ParamPathInfo nodes for parameterized Paths, if any * 參數化路徑的ParamPathInfo節點(如果有的話) * 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 * 在非參數化路徑中啟動成本最低(無論順序如何)的路徑鏈表成員; * 如果沒有非參數化路徑,則為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 * 在非參數化路徑中總成本最低(無論順序如何)的路徑列表成員; * 如果沒有非參數化路徑,則在參數化最少的路徑中總成本最低的路徑 * cheapest_unique_path - for caching cheapest path to produce unique * (no duplicates) output from relation; NULL if not yet requested * 用于緩存最便宜的路徑,以便從關系中產生唯一(無重復)輸出; * 如果無此要求,則為NULL * cheapest_parameterized_paths - best paths for their parameterizations; * always includes cheapest_total_path, even if that's unparameterized * 參數化的最佳路徑;總是包含cheapest_total_path,即使它是非參數化的 * direct_lateral_relids - rels this rel has direct LATERAL references to * 該rel直接LATERAL依賴的rels * lateral_relids - required outer rels for LATERAL, as a Relids set * (includes both direct and indirect lateral references) * LATERAL所需的外部rels,作為Relids集合(包括直接和間接的側向參考) * * If the relation is a base relation it will have these fields set: * 如果關系是一個基本關系,它將設置這些字段: * relid - RTE index (this is redundant with the relids field, but * is provided for convenience of access) * RTE索引(這對于relids字段來說是冗余的,但是為了方便訪問而提供) * rtekind - copy of RTE's rtekind field * RTE's rtekind字段的拷貝 * min_attr, max_attr - range of valid AttrNumbers for rel * 關系有效AttrNumbers的范圍(最大/最小編號) * 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 * 位圖集數組,表示每個屬性所需的最高層joinrel; * 如果設置為0,則需要將該屬性作為最終targetlist的一部分 * attr_widths - cache space for per-attribute width estimates; * zero means not computed yet * 用于每個屬性寬度估計的緩存空間;0表示還沒有計算 * lateral_vars - lateral cross-references of rel, if any (list of * Vars and PlaceHolderVars) * rel的lateral交叉參照,如果有的話(Vars和PlaceHolderVars鏈表) * lateral_referencers - relids of rels that reference this one laterally * (includes both direct and indirect lateral references) * lateral依賴此關系的relids(包括直接&間接lateral依賴) * indexlist - list of IndexOptInfo nodes for relation's indexes * (always NIL if it's not a table) * 關系索引的IndexOptInfo節點鏈表(如果不是表,總是NIL) * pages - number of disk pages in relation (zero if not a table) * 關系的磁盤頁數(如不是表,則為0) * tuples - number of tuples in relation (not considering restrictions) * 關系的元組數統計(還沒有考慮約束條件) * allvisfrac - fraction of disk pages that are marked all-visible * 標記為all-visible的磁盤頁數比例 * subroot - PlannerInfo for subquery (NULL if it's not a subquery) * 用于子查詢的PlannerInfo(如果不是子查詢,則為NULL) * subplan_params - list of PlannerParamItems to be passed to subquery * 要傳遞給子查詢的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. * 對于子查詢,元組和subroot不會在創建RelOptInfo對象時立即設置; * 它們是在set_subquery_pathlist處理對象時填充的。 * * For otherrels that are appendrel members, these fields are filled * in just as for a baserel, except we don't bother with lateral_vars. * 對于其他appendrel成員,這些字段就像base rels一樣被填充, * 除了我們不關心的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: * 如果關系是一個外表或一個外表的連接,這些表都屬于相同的外服務器 * 并被分配給相同的用戶來檢查訪問權限(cf checkAsUser),這些字段將被設置: * * serverid - OID of foreign server, if foreign table (else InvalidOid) * 外部服務器的OID,如不為外部表則為InvalidOid * userid - OID of user to check access as (InvalidOid means current user) * 檢查訪問權限的用戶OID(InvalidOid表示當前用戶) * useridiscurrent - we've assumed that userid equals current user * 我們假設userid為當前用戶 * fdwroutine - function hooks for FDW, if foreign table (else NULL) * FDW的函數鉤子,如不是外部表則為NULL * fdw_private - private state for FDW, if foreign table (else NULL) * FDW的私有狀態,不是外部表則為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: * 下面的兩個字段用于緩存在連接搜索過程中獲取的信息, * 這些信息是關于當這個rel被連接到給定的其他關系時是否被證明是唯一的, * 也就是說,它最多只能有一行匹配來自該連接關系的任何給定行。 * 目前我們只嘗試這樣的證明,因此只填充這些字段,用于base rels; * 但總有一天它們也可以被用來加入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集合的鏈表,每一個都是一組other rels,這些rels已經被證明是唯一的 * 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集合的鏈表,每個集合都是other rels,這些rels試圖證明唯一的,但失敗了 * * The presence of the following fields depends on the restrictions * and joins that the relation participates in: * 以下字段的存在取決于約束條件和關系所參與的連接: * * baserestrictinfo - List of RestrictInfo nodes, containing info about * each non-join qualification clause in which this relation * participates (only used for base rels) * RestrictInfo節點鏈表,其中包含關于此關系參與的每個非連接限定子句的信息(僅用于基礎rels) * baserestrictcost - Estimated cost of evaluating the baserestrictinfo * clauses at a single tuple (only used for base rels) * 在單個元組中解析baserestrictinfo子句的估算成本(僅用于基礎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節點鏈表,其中包含關于此關系參與的每個連接條件子句的信息 * (但請注意,這排除了可能從等價類派生的子句) * has_eclass_joins - flag that EquivalenceClass joins are possible * 用于標記等價類連接是可能的 * * 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中保存一個restrictinfo鏈表只對基礎rels有用, * 因為對于一個join rel,被視為限制子句的子句集會根據我們選擇加入的子關系而變化。(例如,在一個3-base-rel連接中,如果我們加入{1}和{2 3}以生成{1 2 3},則與efs 1和2相關的子句必須被視為限制性子句;但是如果我們加入{1 2}和{3},那么該子句將是{1 2}中的一個限制性子句,不應該在{1 2 3}的級別上再次處理)。因此,在join案例中,節流信息列表出現在單獨的連接路徑(字段join節流信息)中,而不是在父關系中。但是RelOptInfo可以存儲joininfo列表,因為對于給定的rel,無論我們如何形成它都是一樣的。 * * 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存儲在RelOptInfo(用于基本關系)中, * 因為我們知道至少需要它一次(為順序掃描計算成本),并且可能需要它多次來為索引掃描計算成本。 * * If the relation is partitioned, these fields will be set: * 如果關系是分區表,會設置這些字段: * * part_scheme - Partitioning scheme of the relation * 關系的分區schema * nparts - Number of partitions * 關系的分區數 * boundinfo - Partition bounds * 分區邊界信息 * partition_qual - Partition constraint if not the root * 如非root,則該字段存儲分區約束條件 * part_rels - RelOptInfos for each partition * 每個分區的RelOptInfos * partexprs, nullable_partexprs - Partition key expressions * 分區鍵表達式 * partitioned_child_rels - RT indexes of unpruned partitions of * this relation that are partitioned tables * themselves, in hierarchical order * 關系中未修剪(unpruned)分區的RT索引, * 這些分區本身就是分區表,按層次順序排列 * * 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. * 注意:一個基本關系總是只有一組分區鍵, * 但是連接關系的分區鍵可能與被連接的關系的數量一樣多。 * partexprs和nullable_partexp是分別包含part_scheme->partnatts元素的數組。 * 每個元素都是分區鍵表達式的鏈表。 * 對于基本關系,partexprs中的每個鏈表只包含一個表達式, * 并且不填充nullable_partexprs。 * 對于連接關系,partexprs和nullable_partexprs包含來自非空和可空關系resp的分區鍵表達式。 * 這些數組中任意給定位置的鏈表包含的元素與連接關系的數量一樣多。 *---------- */ typedef enum RelOptKind { RELOPT_BASEREL,//基本關系(如基表/子查詢等) RELOPT_JOINREL,//連接產生的關系,要注意的是通過連接等方式產生的結果亦可以視為關系 RELOPT_OTHER_MEMBER_REL, RELOPT_OTHER_JOINREL, RELOPT_UPPER_REL,//上層的關系 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 { //節點標識 NodeTag type; //RelOpt類型 RelOptKind reloptkind; /* all relations included in this RelOptInfo */ //所有關系都有的屬性 //Relids(rtindex)集合 Relids relids; /* set of base relids (rangetable indexes) */ /* size estimates generated by planner */ //規劃器生成的大小估算 //結果元組的估算數量 double rows; /* estimated number of result tuples */ /* per-relation planner control flags */ //規劃器使用的每個關系的控制標記 //是否考慮啟動成本?是,需要保留啟動成本低的路徑 bool consider_startup; /* keep cheap-startup-cost paths? */ //是否考慮參數化?的路徑 bool consider_param_startup; /* ditto for parameterized paths? */ //是否考慮并行處理路徑 bool consider_parallel; /* consider parallel paths? */ /* default result targetlist for Paths scanning this relation */ //掃描該Relation時默認的結果投影列 //Vars/Exprs,成本,行平均大小鏈表 struct PathTarget *reltarget; /* list of Vars/Exprs, cost, width */ /* materialization information */ //物化信息 //訪問路徑鏈表 List *pathlist; /* Path structures */ //路徑鏈表中的ParamPathInfos鏈表 List *ppilist; /* ParamPathInfos used in pathlist */ //并行部分路徑 List *partial_pathlist; /* partial Paths */ //啟動代價最低的路徑 struct Path *cheapest_startup_path; //整體代價最低的路徑 struct Path *cheapest_total_path; //獲取唯一值代價最低的路徑 struct Path *cheapest_unique_path; //參數化代價最低的路徑 List *cheapest_parameterized_paths; /* parameterization information needed for both base rels and join rels */ /* (see also lateral_vars and lateral_referencers) */ //基本通道和連接通道都需要參數化信息 //(參考lateral_vars和lateral_referencers) //使用lateral語法,需依賴的Relids Relids direct_lateral_relids; /* rels directly laterally referenced */ //rel的最小化參數信息 Relids lateral_relids; /* minimum parameterization of rel */ /* information about a base rel (not set for join rels!) */ //reloptkind=RELOPT_BASEREL時使用的數據結構 //relid Index relid; /* Relation ID */ //表空間 Oid reltablespace; /* containing tablespace */ //類型:基表?子查詢?還是函數等等? RTEKind rtekind; /* RELATION, SUBQUERY, FUNCTION, etc */ //最小的屬性編號 AttrNumber min_attr; /* smallest attrno of rel (often <0) */ //最大的屬性編號 AttrNumber max_attr; /* largest attrno of rel */ //屬性數組 Relids *attr_needed; /* array indexed [min_attr .. max_attr] */ //屬性寬度 int32 *attr_widths; /* array indexed [min_attr .. max_attr] */ //關系依賴的LATERAL Vars/PHVs List *lateral_vars; /* LATERAL Vars and PHVs referenced by rel */ //依賴該關系的Relids Relids lateral_referencers; /* rels that reference me laterally */ //該關系的IndexOptInfo鏈表 List *indexlist; /* list of IndexOptInfo */ //統計信息鏈表 List *statlist; /* list of StatisticExtInfo */ //塊數 BlockNumber pages; /* size estimates derived from pg_class */ //元組數 double tuples; /* */ // double allvisfrac; /* ? */ //如為子查詢,存儲子查詢的root PlannerInfo *subroot; /* if subquery */ //如為子查詢,存儲子查詢的參數 List *subplan_params; /* if subquery */ //并行執行,需要多少個workers? int rel_parallel_workers; /* wanted number of parallel workers */ /* Information about foreign tables and foreign joins */ //FWD相關信息 //表或連接的服務器標識符 Oid serverid; /* identifies server for the table or join */ //用戶id標識 Oid userid; /* identifies user to check access as */ //對于當前用戶來說,連接才是有效的 bool useridiscurrent; /* join is only valid for current user */ /* use "struct FdwRoutine" to avoid including fdwapi.h here */ //使用結構體FdwRoutine,避免包含頭文件fdwapi.h struct FdwRoutine *fdwroutine; void *fdw_private; /* cache space for remembering if we have proven this relation unique */ //如果已證明該關系是唯一的,那么這些是用于緩存這些信息的字段 //已知的,可保證唯一的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: */ //用于各種掃描和連接 //如為基本關系,存儲約束條件鏈表 List *baserestrictinfo; /* RestrictInfo structures (if base rel) */ //解析約束表達式的成本? QualCost baserestrictcost; /* cost of evaluating the above */ //最低安全等級 Index baserestrict_min_security; /* min security_level found in * baserestrictinfo */ //連接語句的約束條件信息 List *joininfo; /* RestrictInfo structures for join clauses * involving this rel */ //是否存在等價類連接? 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) */ //最高層的父關系Relids Relids top_parent_relids; /* Relids of topmost parents (if "other" * rel) */ /* used for partitioned relations */ //分區表使用 //分區的schema PartitionScheme part_scheme; /* Partitioning scheme. */ //分區數 int nparts; /* number of partitions */ //分區邊界信息 struct PartitionBoundInfoData *boundinfo; /* Partition bounds */ //分區約束 List *partition_qual; /* partition constraint */ //分區的RelOptInfo數組 struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions, * stored in the same order of bounds */ //非空分區鍵表達式鏈表 List **partexprs; /* Non-nullable partition key expressions. */ //可為空的分區鍵表達式 List **nullable_partexprs; /* Nullable partition key expressions. */ // 分區子表RT Indexes鏈表 List *partitioned_child_rels; /*List of RT indexes. */ } RelOptInfo;
AppendRelInfo
Append-relation信息.
當我們將可繼承表(分區表)或UNION-ALL子查詢展開為“追加關系”(本質上是子RTE的鏈表)時,為每個子RTE構建一個AppendRelInfo。
AppendRelInfos鏈表指示在展開父節點時必須包含哪些子rte,每個節點具有將引用父節點的Vars轉換為引用該子節點的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. * 當我們將可繼承表(分區表)或UNION-ALL子查詢展開為“追加關系”(本質上是子RTE的鏈表)時, * 為每個子RTE構建一個AppendRelInfo。 * AppendRelInfos鏈表指示在展開父節點時必須包含哪些子rte, * 每個節點具有將引用父節點的Vars轉換為引用該子節點的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. * 這些結構體保存在PlannerInfo節點的append_rel_list中。 * 注意,只是將所有的結構體放入一個鏈表中,并在希望展開任何父類時掃描整個鏈表。 * 本可以使用更復雜的數據結構(例如,每個父節點一個列表), * 但是在提取子查詢之類的操作中更新它會更困難, * 而且實際上也不會更容易掃描。 * 考慮到典型的查詢不會有很多不同的附加項,因此似乎不值得將事情復雜化。 * * 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. * 注意:計劃準備階段完成后, * 當且僅當它的“inh”標志已設置時,給定的RTE是一個append parent在append_rel_list中的一個條目。 * 我們為沒有child的平面表清除“inh”標記, * 同時(有濫用標記的嫌疑)為UNION ALL查詢中的子查詢RTEs設置“inh”標記。 * 這樣可以避免對append_rel_list進行無用的搜索。 * * 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. * 注意:數據結構假定附加的rel成員是獨立的baserels。 * 這對于繼承來說是可以的,但是如果UNION ALL member子查詢包含一個join, * 那么它將阻止我們提取UNION ALL member子查詢。 * 雖然可以用更復雜的數據結構解決這個問題,但目前沒有太大意義,因為該計劃可能不會有任何改進。 */ 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. * 這些字段惟一地標識這個append relationship。 * 對于同一個parent_relid可以有(實際上應該總是)多個AppendRelInfos, * 但是每個child_relid不能有多個AppendRelInfos, * 因為給定的RTE不能是多個append parent的子節點。 */ 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. * 對于繼承appendrel,父類和子類都是普通關系, * 我們將它們的rowtype OIDs存儲在這里,用于轉換whole-row Vars。 * 對于UNION-ALL appendrel,父查詢和子查詢都是沒有指定行類型的子查詢, * 我們在這里存儲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. * 這個列表的第N個元素是一個Var或表達式,表示與父元素的第N列對應的子列。 * 這用于將引用parent rel的Vars轉換為對子rel的引用。 * 如果鏈表元素與父元素的已刪除列相對應,則該元素為NULL * (這只適用于繼承情況,而不是UNION ALL)。 * 對于繼承情況,鏈表元素總是簡單的變量,但是可以是UNION ALL情況下的任意表達式。 * * 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. * 注意,我們只存儲用戶列的條目(attno > 0)。 * Whole-row Vars是大小寫敏感的,系統列(attno < 0)不需要特別的轉換, * 因為它們的attno對所有表都是相同的。 * * Caution: the Vars have varlevelsup = 0. Be careful to adjust as needed * when copying into a subquery. * 注意:Vars的varlevelsup = 0。 * 在將數據復制到子查詢時,要注意根據需要進行調整。 */ //child's Vars中的表達式 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存儲在這里用于繼承, * 如為UNION ALL,則這里存儲的是InvalidOid。 * 只有在試圖引用已刪除的父列時,才需要這樣做來幫助生成錯誤消息。 */ Oid parent_reloid; /* OID of parent relation */ } AppendRelInfo;
PlannerInfo
該數據結構用于存儲查詢語句在規劃/優化過程中的相關信息
/*---------- * PlannerInfo * Per-query information for planning/optimization * 用于規劃/優化的每個查詢信息 * * 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. * 在所有計劃程序例程中,這個結構通常稱為“root”。 * 除了原始查詢之外,它還保存到所有計劃器工作狀態的鏈接。 * 注意,目前計劃器會毫無節制的修改傳入的查詢數據結構,相信總有一天這種情況會停止的。 *---------- */ struct AppendRelInfo; typedef struct PlannerInfo { NodeTag type;//Node標識 //查詢樹 Query *parse; /* the Query being planned */ //當前的planner全局信息 PlannerGlobal *glob; /* global info for current planner run */ //查詢層次,1標識最高層 Index query_level; /* 1 at the outermost Query */ // 如為子計劃,則這里存儲父計劃器指針,NULL標識最高層 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包含該查詢級別需要提供給當前計劃的較低查詢級別的表達式。 * outer_params包含PARAM_EXEC Params的參數,外部查詢級別將使該查詢級別可用這些參數。 */ 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”的指針 * (有關RelOptInfo的更多信息,請參見注釋)。 * 它由可范圍表索引建立索引(因此條目0總是被浪費)。 * 當RTE與基本關系(如JOIN RTE或未被引用的視圖RTE時)不相對應 * 或者如果RelOptInfo還沒有生成,條目可以為NULL。 */ //RelOptInfo數組,存儲"base rels",比如基表/子查詢等. //該數組與RTE的順序一一對應,而且是從1開始,因此[0]無用 */ struct RelOptInfo **simple_rel_array; /* All 1-rel RelOptInfos */ int simple_rel_array_size; /* 數組大小,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的長度與simple_rel_array相同, * 并保存指向相應范圍表條目的指針。 * 這使我們可以避免執行rt_fetch(),因為一旦擴展了大型繼承集,rt_fetch()可能會有點慢。 */ //RTE數組 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與上述數組的長度相同, * 并保存指向對應的AppendRelInfo條目的指針,該條目由child_relid索引, * 如果沒有索引則為NULL。 * 如果append_rel_list為空,則不分配數組本身。 */ //處理集合操作如UNION ALL時使用和分區表時使用 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是查詢中所有base relids(但不是“other” relids)的一個Relids集合; * 也就是說,這是需要形成的最終連接的Relids標識符。 * 這是在開始創建路徑之前在make_one_rel中計算的。 */ 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等下面可能為空的樹。 * 這是在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是在計劃執行中考慮的所有連接關系RelOptInfos的鏈表。 * 對于小問題,只需要掃描鏈表執行查找,但是當存在許多連接關系時, * 需要構建一個散列表來進行更快的查找。 * 當join_rel_hash不為空時,哈希表是有效可用于查詢的。 * 注意,即使在使用哈希表進行查找時,仍然維護該鏈表;這簡化了GEQO(遺傳算法)的生命周期。 */ //參與連接的Relation的RelOptInfo鏈表 List *join_rel_list; /* list of join-relation RelOptInfos */ //可加快鏈表訪問的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. * 在執行動態規劃算法的連接搜索時,join_rel_level[k]是k級的所有連接關系RelOptInfos的列表, * join_cur_level是當前級別。 * 新的連接關系RelOptInfos會自動添加到join_rel_level[join_cur_level]鏈表中。 * 如果不使用join_rel_level,則為NULL。 */ //RelOptInfo指針鏈表數組,k層的join存儲在[k]中 List **join_rel_level; /* lists of join-relation RelOptInfos */ //當前的join層次 int join_cur_level; /* index of list being extended */ //查詢的初始化計劃鏈表 List *init_plans; /* init SubPlans for query */ //CTE子計劃ID鏈表 List *cte_plan_ids; /* per-CTE-item list of subplan IDs */ //MULTIEXPR子查詢輸出的參數鏈表的鏈表 List *multiexpr_params; /* List of Lists of Params for MULTIEXPR * subquery outputs */ //活動的等價類鏈表 List *eq_classes; /* list of active EquivalenceClasses */ //規范化的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 */ //窗口函數路徑鍵 List *window_pathkeys; /* pathkeys of bottom window, if any */ //distinctClause路徑鍵 List *distinct_pathkeys; /* distinctClause pathkeys, if any */ //排序路徑鍵 List *sort_pathkeys; /* sortClause pathkeys, if any */ //已規范化的分區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為上層處理選擇的結果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在這里傳回它最終處理過的targetlist,用于重新標記已完成計劃的最頂層tlist。 */ ////最后需處理的投影列 List *processed_tlist; /* Fields filled during create_plan() for use in setrefs.c */ //setrefs.c中在create_plan()函數調用期間填充的字段 //分組函數屬性映射 AttrNumber *grouping_map; /* for GroupingFunc fixup */ //MinMaxAggInfos鏈表 List *minmax_aggs; /* List of MinMaxAggInfos */ //內存上下文 MemoryContext planner_cxt; /* context holding PlannerInfo */ //關系的page計數 double total_table_pages; /* # of pages in all tables of query */ //query_planner輸入參數:元組處理比例 double tuple_fraction; /* tuple_fraction passed to query_planner */ //query_planner輸入參數:limit_tuple double limit_tuples; /* limit_tuples passed to query_planner */ //表達式的最小安全等級 Index qual_security_level; /* minimum security_level for quals */ /* Note: qual_security_level is zero if there are no securityQuals */ //注意:如果沒有securityQuals, 則qual_security_level是NULL(0) //如目標relation是分區表的child/partition/分區表,則通過此字段標記 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 */ //是否存在標記為LATERAL的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 bool hasPseudoConstantQuals; /* true if any RestrictInfo has * pseudoconstant = true */ //是否存在遞歸語句 bool hasRecursion; /* true if planning a recursive WITH item */ /* These fields are used only when hasRecursion is true: */ //這些字段僅在hasRecursion為T時使用: //工作表的PARAM_EXEC ID int wt_param_id; /* PARAM_EXEC ID for the work table */ //非遞歸模式的訪問路徑 struct Path *non_recursive_path; /* a path for non-recursive term */ /* These fields are workspace for createplan.c */ //這些字段用于createplan.c //當前節點之上的外部rels Relids curOuterRels; /* outer rels above current node */ //未賦值的NestLoopParams參數 List *curOuterParams; /* not-yet-assigned NestLoopParams */ /* optional private data for join_search_hook, e.g., GEQO */ //可選的join_search_hook私有數據,例如GEQO void *join_search_private; /* Does this query modify any partition key columns? */ //該查詢是否更新分區鍵列? bool partColsUpdated; } PlannerInfo;
“PostgreSQL中分區表查詢相關的重要數據結構有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。