In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)05/31 Report--
This article will explain in detail how to use the prune_append_rel_partitions- > get_matching_partitions function in PostgreSQL. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.
I. data structure
PartitionScheme
According to the design, the partition scheme contains only the general properties of the partition method (list and range, the number of partition columns, and the type information of each partition column), but does not contain specific partition boundary information.
/ * If multiple relations are partitioned the same way, all such partitions * will have a pointer to the same PartitionScheme. A list of PartitionScheme * objects is attached to the PlannerInfo. By design, the partition scheme * incorporates only the general properties of the partition method (LIST vs. * RANGE, number of partitioning columns and the type information for each) * and not the specific bounds. * if multiple relationships are partitioned in the same way, all of these partitions will have pointers to the same PartitionScheme. * A linked list of PartitionScheme objects is appended to the PlannerInfo. * by design, the partition scheme contains only the general properties of the partition method (list and range, number of partition columns, and type information for each partition column), * without specific boundaries. * * We store the opclass-declared input datatypes instead of the partition key * datatypes since the former rather than the latter are used to compare * partition bounds. Since partition key data types and the opclass declared * input data types are expected to be binary compatible (per ResolveOpClass), * both of those should have same byval and length properties. * We store the input data type of opclass-declared instead of the partition key data type, * because the former is used to compare partition boundaries, not the latter. * since the partitioning key data type and the input data type of opclass-declared are expected to be binary compatible (per ResolveOpClass), * they should have the same byval and length properties. * / typedef struct PartitionSchemeData {char strategy; / * partition policy; number of partition strategy * / int16 partnatts; / * partition attributes; OIDs;OIDs of opclass declared input data types * / Oid * partcollation of the input data type declared by the number of partition attributes * / Oid * partopfamily; / * operator family OIDs;OIDs of operator families * / Oid * partopcintype; / * opclass / * partition collation OIDs;OIDs of partitioning collations * / / * Cached information about partition key data types. * / / caches information about the partitioning key data type. Int16 * parttyplen; bool * parttypbyval; / * Cached information about partition comparison functions. * / / caches information about partition comparison functions. FmgrInfo * partsupfunc;} PartitionSchemeData;typedef struct PartitionSchemeData * PartitionScheme
PartitionPruneXXX
Data structures to be used during Prune execution, including PartitionPruneStep/PartitionPruneStepOp/PartitionPruneCombineOp/PartitionPruneStepCombine
/ * * Abstract Node type for partition pruning steps (there are no concrete * Nodes of this type) * Abstract node type for partition pruning step pruning (there is no concrete node of this type). * * step_id is the global identifier of the step within its pruning context. * step_id is the global identifier of the step in its pruning pruning context. * / typedef struct PartitionPruneStep {NodeTag type; int step_id;} PartitionPruneStep; / * * PartitionPruneStepOp-Information to prune using a set of mutually AND'd * OpExpr clauses * PartitionPruneStepOp-use a set of OpExpr conditional clauses of the AND operation to prune prune information * * This contains information extracted from up to partnatts OpExpr clauses, * where partnatts is the number of partition key columns. 'opstrategy' is the * strategy of the operator in the clause matched to the last partition key. * 'exprs' contains expressions which comprise the lookup key to be passed to * the partition bound search function. 'cmpfns' contains the OIDs of * comparison functions used to compare aforementioned expressions with * partition bounds. Both 'exprs' and' cmpfns' contain the same number of * items, up to partnatts items. * it contains information extracted from the partnatts OpExpr clause, where partnatts is the number of partition key columns. * "opstrategy" is the policy of the operator that matches the last partitioning key in the clause. * 'exprs' contains expressions that contain the lookup key to be passed to the partition binding search function. * "cmpfns" contains the OIDs used to compare the above expression with the comparison function of the partition boundary. * "exprs" and "cmpfns" contain the same number of entries, with a maximum of partnatts entries. * * Once we find the offset of a partition bound using the lookup key, we * determine which partitions to include in the result based on the value of * 'opstrategy'. For example, if it were equality, we'd return just the * partition that would contain that key or a set of partitions if the key * didn't consist of all partitioning columns. For non-equality strategies, * we'd need to include other partitions as appropriate. * once we use the find key to find the offset bound to the partition, * we will determine which partitions are included in the result based on the value of "opstrategy". * for example, if it is equal, we return only the partition that contains the key, or if the key does not contain all partition columns, * returns a set of partitions. * for non-equivalent cases, other partitions need to be included appropriately. * * 'nullkeys' is the set containing the offset of the partition keys (0 to * partnatts-1) that were matched to an IS NULL clause. This is only * considered for hash partitioning as we need to pass which keys are null * to the hash partition bound search function. It is never possible to * have an expression be present in 'exprs' for a given partition key and * the corresponding bit set in' nullkeys'. * 'nullkeys' is a collection of partitioning key (0 to partnatts-1) offsets that match the is NULL clause. * this only applies to hash partitions because we need to pass which keys as null to the hash partition binding search function. * for a given partition key and the corresponding bit set in "nullkeys", it is not possible to have an expression in "exprs". * / typedef struct PartitionPruneStepOp {PartitionPruneStep step; StrategyNumber opstrategy; List * exprs; List * cmpfns; Bitmapset * nullkeys;} PartitionPruneStepOp;/* * PartitionPruneStepCombine-Information to prune using a BoolExpr clause * PartitionPruneStepCombine-Information about using BoolExpr condition prune * * For BoolExpr clauses, we combine the set of partitions determined for each * of the argument clauses. * for the BoolExpr clause, we combine the partition set determined by each parameter clause. * / typedef enum PartitionPruneCombineOp {PARTPRUNE_COMBINE_UNION, PARTPRUNE_COMBINE_INTERSECT} PartitionPruneCombineOp;typedef struct PartitionPruneStepCombine {PartitionPruneStep step; PartitionPruneCombineOp combineOp; List * source_stepids;} PartitionPruneStepCombine;/* The result of performing one PartitionPruneStep * / / the result of the PartitionPruneStep step typedef struct PruneStepResult {/ * The offsets of bounds (in a table's boundinfo) whose partition is * selected by the pruning step. * is the partition boundary selected by the pruning step (in the data table boundinfo) offset * / Bitmapset * bound_offsets; bool scan_default; / * scan the default partition? Is Scan the default partition * / bool scan_null; / * a null scan partition? Scan the partition for NULL values? * /} PruneStepResult; II. Source code interpretation
The get_matching_partitions function determines the partitions that are still "alive" after the partition pruning.
/ * * get_matching_partitions * Determine partitions that survive partition pruning * determines the partitions that still exist after the partition trims the pruning. * * Returns a Bitmapset of the RelOptInfo- > part_rels indexes of the surviving * partitions. * return the RelOptInfo- > part_rels index bitmap of the partition that still exists after pruning. * / Bitmapset * get_matching_partitions (PartitionPruneContext * context, List * pruning_steps) {Bitmapset * result; int num_steps = list_length (pruning_steps), I; PruneStepResult * * results, * final_result; ListCell * lc; / * If there are no pruning steps then all partitions match. * / / if there is no pruning step, all partitions if (num_steps = = 0) {Assert (context- > nparts > 0); return bms_add_range (NULL, 0, context- > nparts-1);} / * * Allocate space for individual pruning steps to store its result are considered. Each * slot will hold a PruneStepResult after performing a given pruning step. * Later steps may use the result of one or more earlier steps. The * result of applying all pruning steps is the value contained in the slot * of the last pruning step. * allocate space for a single pruning step to store the results. * each slot will hold the pruning after performing a given pruning step. * later steps can use the results of one or more of the previous steps. * the result of applying all steps is the value contained in the slot of the last step. * / results = (PruneStepResult * *) palloc0 (num_steps * sizeof (PruneStepResult *)); foreach (lc, pruning_steps) / / traversal step {PartitionPruneStep * step = lfirst (lc) Switch (nodeTag (step)) {case T_PartitionPruneStepOp: results [step-> step_id] = perform_pruning_base_step (context, (PartitionPruneStepOp *) step); / / execute pruning basic step break Case T_PartitionPruneStepCombine: results [step-> step_id] = perform_pruning_combine_step (context, (PartitionPruneStepCombine *) step, results); / / execute pruning composition step break Default: elog (ERROR, "invalid pruning step type:% d", (int) nodeTag (step));} / * * At this point we know the offsets of all the datums whose corresponding * partitions need to be in the result, including special null-accepting * and default partitions. Collect the actual partition indexes now. * so far, we have known the offset of all data for the corresponding partitions required in the results, * including special partitions that accept null and default partitions. * now collect the actual partition index. * / final_result = results [num _ steps-1]; / / final result Assert (final_result! = NULL); I =-1; result = NULL; while ((I = bms_next_member (final_result- > bound_offsets, I) > = 0) {int partindex = context- > boundinfo- > indexes [I] / / Partition number / * * In range and hash partitioning cases, some slots may contain-1, * indicating that no partition has been defined to accept a given * range of data or for a given remainder, respectively. The default * partition, if any, in case of range partitioning, will be added to * the result, because the specified range still satisfies the query's * conditions. * range partitions and hash partitions, some slot may contain-1, * this means that no partitions are defined that accept a given range of data or a given remainder. * in the case of range partitions, the default partition, if any, will be added to the results, * because the specified range still meets the conditions of the query. * / if (partindex > = 0) result = bms_add_member (result, partindex);} / * Add the null and/or default partition if needed and if present. * / / add NULL and / or default partitions if necessary. If (final_result- > scan_null) {Assert (context- > strategy = = PARTITION_STRATEGY_LIST); Assert (partition_bound_accepts_nulls (context- > boundinfo)); result = bms_add_member (result, context- > boundinfo- > null_index);} if (final_result- > scan_default) {Assert (context- > strategy = = PARTITION_STRATEGY_LIST | context- > strategy = = PARTITION_STRATEGY_RANGE) Assert (partition_bound_has_default (context- > boundinfo); result = bms_add_member (result, context- > boundinfo- > default_index);} return result;} / * * perform_pruning_base_step * Determines the indexes of datums that satisfy conditions specified in * 'opstep'. * determine the data index that meets the criteria specified in "opstep". * Result also contains whether special null-accepting and/or default * partition need to be scanned. * the results also include whether special acceptable null and / or default partitions need to be scanned. * / static PruneStepResult * perform_pruning_base_step (PartitionPruneContext * context, PartitionPruneStepOp * opstep) {ListCell * lc1, * lc2; int keyno, nvalues; Datum values [part _ MAX_KEYS]; FmgrInfo * partsupfunc; int stateidx; / * * There better be the same number of expressions and compare functions. * it is better to have the same number of expressions and comparison functions. * / Assert (list_length (opstep- > exprs) = = list_length (opstep- > cmpfns); nvalues = 0; lc1 = list_head (opstep- > exprs); lc2 = list_head (opstep- > cmpfns); / * Generate the partition lookup key that will be used by one of the * get_matching_*_bounds functions called below. * generate the partition lookup key that will be used by the get_matching_*_bounds function called below. * / for (keyno = 0; keyno)
< context-> < partnatts; i++) isnull[i] = bms_is_member(i, nullkeys); greatest_modulus = get_hash_partition_greatest_modulus(boundinfo); rowHash = compute_partition_hash_value(partnatts, partsupfunc, values, isnull); if (partindices[rowHash % greatest_modulus] >= 0) result- > bound_offsets = bms_make_singleton (rowHash% greatest_modulus);} else {/ * Getting here means at least one hash partition exists. * / / the execution of the program here means that there is at least one hash partition Assert (boundinfo- > ndatums > 0); result- > bound_offsets = bms_add_range (NULL, 0, boundinfo- > ndatums-1);} / * There is neither a special hash null partition or the default hash * partition. * either there is a special hash null partition or the default hash partition * / result- > scan_null = result- > scan_default = false; return result;} 3. Trace analysis
The test script is as follows
Testdb=# explain verbose select * from t_hash_partition where C1 = 1 OR C1 = 2 QUERY PLAN -Append (cost=0.00..30.53 rows=6 width=200)-> Seq Scan on public.t_hash_partition_1 (cost=0.00..15.25 rows=3 width=200) Output: t_hash_partition_1.c1 T_hash_partition_1.c2, t_hash_partition_1.c3 Filter: (t_hash_partition_1.c1 = 1) OR (t_hash_partition_1.c1 = 2)-> Seq Scan on public.t_hash_partition_3 (cost=0.00..15.25 rows=3 width=200) Output: t_hash_partition_3.c1, t_hash_partition_3.c2 T_hash_partition_3.c3 Filter: (t_hash_partition_3.c1 = 1) OR (t_hash_partition_3.c1 = 2)) (7 rows)
Start gdb and set breakpoint
(gdb) b get_matching_partitionsBreakpoint 1 at 0x804d3b: file partprune.c, line 619. (gdb) cContinuing.Breakpoint 1, get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:619619 int num_steps = list_length (pruning_steps), (gdb) n626 if (num_steps = = 0)
Check the input parameters. Pruning_steps is a linked list with 3 ITEM.
(gdb) p * pruning_steps$1 = {type = T_List, length = 3, head = 0x14d52d8, tail = 0x14d58d0}
The three ITEM types of pruning_steps are PartitionPruneStepOp/PartitionPruneStepOp/PartitionPruneStepCombine
The expr of the first and second ITEM is Const, that is, constants 1 and 2
(gdb) p * (Node *) pruning_steps- > head- > data.ptr_value$2 = {type = T_PartitionPruneStepOp}-> Node type (gdb) p * (PartitionPruneStepOp *) pruning_steps- > head- > data.ptr_value$3 = {step = {type = T_PartitionPruneStepOp, step_id = 0}, opstrategy = 1, exprs = 0x14d52a0, cmpfns = 0x14d5240, nullkeys = 0x0} (gdb) set $ppso= (PartitionPruneStepOp *) pruning_steps- > head- > data.ptr_value (gdb) p * $ppso- > exprs$4 = {type = T_List, T_List = 1 Head = 0x14d5278, tail = 0x14d5278} (gdb) p * (Node *) $ppso- > exprs- > head- > data.ptr_value$5 = {type = T_Const} (gdb) p * (Const *) $ppso- > exprs- > head- > data.ptr_value$6 = {xpr = {type = T_Const}, consttype = 23, consttypmod =-1, constcollid = 0, constlen = 4, constvalue = 1, constisnull = false, constbyval = true, location = 42}-- > expression for step 1 Constant 1 (gdb) set $ppso= (PartitionPruneStepOp *) pruning_steps- > head- > next- > data.ptr_value (gdb) p * (Const *) $ppso- > exprs- > head- > data.ptr_value$7 = {xpr = {type = T_Const}, consttype = 23, consttypmod =-1, constcollid = 0, constlen = 4, constvalue = 2, constisnull = false, constbyval = true, location = 52}-- > expression for step 2 Constant 2 (gdb) p * (Node *) pruning_steps- > head- > next- > next- > data.ptr_value$8 = {type = T_PartitionPruneStepCombine} (gdb) set $ppsc= (PartitionPruneStepCombine *) pruning_steps- > head- > next- > next- > data.ptr_value (gdb) p * $ppsc$9 = {step = {type = T_PartitionPruneStepCombine, step_id = 2}, combineOp = PARTPRUNE_COMBINE_UNION, source_stepids = 0x14d5480}-- > step 3. The combination operation is PARTPRUNE_COMBINE_UNION.
Allocate memory for step results
(gdb) n640 palloc0 (num_steps * sizeof (PruneStepResult *)); (gdb) p num_steps$10 = 3 (gdb) n639 results = (PruneStepResult * *) (gdb) 641 foreach (lc, pruning_steps)
Start traversing the pruning step and enter the perform_pruning_base_step function
(gdb) 643 PartitionPruneStep * step= lfirst (lc); (gdb) 645 switch (nodeTag (step)) (gdb) 648 results [step-> step_id] = (gdb) step649 perform_pruning_base_step (context, (gdb) perform_pruning_base_step (context=0x7fff4a5e3930, opstep=0x14d4e98) at partprune.c:29952995 Assert (list_length (opstep- > exprs) = list_length (opstep- > cmpfns))
Perform_pruning_base_step- > check the input parameters. The comparison function is a function of OID=425.
(gdb) p * opstep- > cmpfns$12 = {type = T_OidList, length = 1, head = 0x14d5218, tail = 0x14d5218} (gdb) p opstep- > cmpfns- > head- > data.oid_value$16 = 425 (gdb) n2998 lc1 = list_head (opstep- > exprs); (gdb) 2999 lc2 = list_head (opstep- > cmpfns); (gdb)
Perform_pruning_base_step- > traversing the partition key
(gdb) 3005 for (keyno = 0; keyno)
< context->Partnatts; keyno++) (gdb) 3012 if (bms_is_member (keyno, opstep- > nullkeys))-- > No null bond (gdb) 3019 if (keyno > nvalues & & context- > strategy = = PARTITION_STRATEGY_RANGE)-> nvalues is 0 (gdb) p nvalues$17 = 0 (gdb) n3022 if (lc1! = NULL) (gdb) 3028 expr = lfirst (lc1) The expression in the get step is actually constant 1 (gdb) 3029 stateidx = PruneCxtStateIdx (context- > partnatts,-- > stateidx is 0 (gdb) p * expr$18 = {type = T_Const} (gdb) p * (Const *) expr$19 = {xpr = {type = T_Const}, consttype = 23, consttypmod =-1, constcollid = 0, constlen = 4, constvalue = 1, constisnull = false, constbyval = true Location = 42} (gdb) n3031 if (partkey_datum_from_expr (context, expr, stateidx, (gdb) p stateidx$20 = 0 (gdb) n3041 if (isnull)-> non-NULL (gdb) p isnull$21 = false
Perform_pruning_base_step- > get the comparison function for processing
(gdb) n3054 cmpfn = lfirst_oid (lc2);-> OID=425 (gdb) 3055 Assert (OidIsValid (cmpfn)) (gdb) 3056 if (cmpfn! = context- > stepcmpfuncs [stateidx] .fn _ oid)-- > fn_oid is 0 (gdb) 3064 if (cmpfn = = context- > partsupfunct [keyno] .FN _ oid)-> fn_oid is 425 (gdb) p context- > stepcmpfuncsstateidx] .FN _ oid$22 = 0 (gdb) p context- > p artsupfunct [keyno] .fn _ oid$23 = 425 (gdb) n3065 Fmgr_info_copy (& context- > stepcmpfuncs [stateidx] (gdb) 3066 & context- > partsupfunc [keyno], (gdb) 3065 fmgr_info_copy (& context- > stepcmpfuncs [stateidx], (gdb) 3066 & context- > partsupfunc [keyno], (gdb) 3065 fmgr_info_copy (& context- > stepcmpfuncs [stateidx]) -> copy function (gdb) 3073 values [keyno] = datum -- > setting value (gdb) p datum$24 = 1 (gdb) n3074 nvalues++; (gdb) 3077 lc1 = lnext (lc1); (gdb) 3078 lc2 = lnext (lc2); (gdb)
Perform_pruning_base_step- > complete the partition key traversal
(gdb) n3005 for (keyno = 0; keyno)
< context->Partnatts; keyno++) (gdb) 3086 stateidx = PruneCxtStateIdx (context- > partnatts, opstep- > step.step_id, 0); (gdb) 3087 partsupfunc = & context- > stepcmpfuncs [stateidx]; (gdb) 3089 switch (context- > strategy) (gdb) 3092 return get_matching_hash_bounds (context, (gdb))
Perform_pruning_base_step- > enter the get_matching_hash_bounds function
(gdb) 3092 return get_matching_hash_bounds (context, (gdb) step3093 opstep- > opstrategy, (gdb) 3092 return get_matching_hash_bounds (context, (gdb) get_matching_hash_bounds (context=0x7fff4a5e3930, opstrategy=1, values=0x7fff4a5e3750, nvalues=1, partsupfunc=0x14d3068, nullkeys=0x0) at partprune.c:21562156 PruneStepResult * result = (PruneStepResult *) palloc0 (sizeof (PruneStepResult)); (gdb)
Get_matching_hash_bounds- > variable assignment
(gdb) n2157 PartitionBoundInfo boundinfo = context- > boundinfo; (gdb) 2158 int * partindices = boundinfo- > indexes; (gdb) 2159 int partnatts = context- > partnatts; (gdb) 2165 Assert (context- > strategy = = PARTITION_STRATEGY_HASH); (gdb) 2172 if (nvalues + bms_num_members (nullkeys) = = partnatts) (gdb)
Get_matching_hash_bounds- > partition boundary information. There are 6 partitions with an Index of 0-5.
(gdb) p boundinfo$25 = (PartitionBoundInfo) 0x14d32a0 (gdb) p * boundinfo$26 = {strategy = 104 'hacks, ndatums = 6, datums = 0x14d32f8, kind = 0x0, indexes = 0x14d2e00, null_index =-1 Default_index =-1} (gdb) p * boundinfo- > datums$27 = (Datum *) 0x14d3350 (gdb) p * * boundinfo- > datums$28 = 6 (gdb) p * * boundinfo- > indexesCannot access memory at address 0x0 (gdb) p * boundinfo- > indexes$29 = 0 (gdb) p boundinfo- > indexes [0] $30 = 0 (gdb) p boundinfo- > indexes [1] $31 = 1 (gdb) p boundinfo- > indexes [5] $32 = 5 (gdb)
Get_matching_hash_bounds- > Partition Index and Partition key
(gdb) p * partindices$33 = 0 (gdb) p partnatts$34 = 1 (gdb) (gdb) p nvalues$35 = 1 (gdb) p bms_num_members (nullkeys) $36 = 0
Get_matching_hash_bounds- > iterate through the partition key to determine whether the value falls in the partition
(gdb) n2178 Assert (opstrategy = = HTEqualStrategyNumber | | nvalues = = 0); (gdb) 2180 for (I = 0; I)
< partnatts; i++)(gdb) 2181 isnull[i] = bms_is_member(i, nullkeys);(gdb) 2180 for (i = 0; i < partnatts; i++)(gdb) 2183 greatest_modulus = get_hash_partition_greatest_modulus(boundinfo);(gdb) 2184 rowHash = compute_partition_hash_value(partnatts, partsupfunc,(gdb) 2187 if (partindices[rowHash % greatest_modulus] >= 0)
Get_matching_hash_bounds- >
(gdb) p values$43 = (Datum *) 0x7fff4a5e3750 (gdb) p * values$44 = 1-> constraint (gdb) p isnull [0] $38 = false-> not NULL (gdb) p greatest_modulus$39 = 6-> 6 partitions (gdb) p rowHash$40 = 11274504255086170040-> values calculated hash value (gdb) p rowHash% greatest_modulus$41 = 2-> partition (gdb) p partindices [2] $42 = 2-> exists the partition (gdb)
Get_matching_hash_bounds- > return the result (bound_offsets- > words=4, that is, number 2)
(gdb) n2189 bms_make_singleton (rowHash% greatest_modulus); (gdb) 2188 result- > bound_offsets = (gdb) 2203 result- > scan_null = result- > scan_default = false; (gdb) 2205 return result (gdb) 2206} (gdb) p * result$45 = {bound_offsets = 0x14d59b8, scan_default = false, scan_null = false} (gdb) p * result- > bound_offsets$46 = {nwords = 1, words = 0x14d59bc} (gdb) p * result- > bound_offsets- > words$47 = 4 (gdb)
Back to get_matching_partitions
(gdb) nperform_pruning_base_step (context=0x7fff4a5e3930, opstep=0x14d4e98) at partprune.c:31193119} (gdb) get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:648648 results [step-> step_id] = (gdb) 651 break; (gdb) 641 foreach (lc, pruning_steps) (gdb) 643 PartitionPruneStep * step= lfirst (lc); (gdb) 645 switch (nodeTag (step)) (gdb) p
Continue with the steps to enter perform_pruning_combine_step
654 results [step-> step_id] = (gdb) 655 perform_pruning_combine_step (context, (gdb) stepperform_pruning_combine_step (context=0x7fff4a5e3930, cstep=0x14d5898, step_results=0x14d5958) at partprune.c:31363136 PruneStepResult * result = NULL; (gdb)
Perform_pruning_combine_step- > enter the PARTPRUNE_COMBINE_UNION processing logic
(gdb) n3143 result = (PruneStepResult *) palloc0 (sizeof (PruneStepResult)); (gdb) 3144 if (list_length (cstep- > source_stepids) = = 0) (gdb) 3154 switch (cstep- > combineOp) (gdb) 3157 foreach (lc1, cstep- > source_stepids) (gdb) (gdb) p * cstep$49 = {step = {type = T_PartitionPruneStepCombine, step_id = 2}, combineOp = PARTPRUNE_COMBINE_UNION, source_stepids = 0x14d5480}
Perform_pruning_combine_step- > iterate through the source step of the combination step cstep- > source_stepids, merging the results of these steps
(gdb) n3159 int step_id = lfirst_int (lc1); (gdb) 3174 result- > bound_offsets = bms_add_members (result- > bound_offsets, (gdb) 3178 if (! result- > scan_null) (gdb) 3179 result- > scan_null = step_result- > scan_null (gdb) 3180 if (! result- > scan_default) (gdb) 3181 result- > scan_default = step_result- > scan_default; (gdb) 3157 foreach (lc1, cstep- > source_stepids) (gdb) 3183 break; (gdb) 3223 return result; (gdb)
Perform_pruning_combine_step- > final result
(gdb) p * result$54 = {bound_offsets = 0x14d5a48, scan_default = false, scan_null = false} (gdb) p * result- > bound_offsets$55 = {nwords = 1, words = 0x14d5a4c} (gdb) p * result- > bound_offsets- > words$56 = 5
Perform_pruning_combine_step- > back to get_matching_partitions
(gdb) n3224} (gdb) get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:654654 results [step-> step_id] =
Complete the processing of all steps
(gdb) n658 break; (gdb) 641 foreach (lc, pruning_steps) (gdb) n671 final_result = results [num _ steps-1]; (gdb) 672 Assert (final_result! = NULL); (gdb)
Construct the resulting bitmap
(I = bms_next_member (final_result- > bound_offsets, I) > = 0) (gdb) n677 int partindex = context- > boundinfo- > indexes [I]; (gdb) 687 if (partindex > = 0) (gdb) 688 result = bms_add_member (result, partindex); (gdb)
Complete the call
Gdb) 675 while ((I = bms_next_member (final_result- > bound_offsets, I) > = 0) (gdb) 692 if (final_result- > scan_null) (gdb) 698 if (final_result- > scan_default) (gdb) 706 return result (gdb) 707} (gdb) this is the end of the article on "how to use the prune_append_rel_partitions- > get_matching_partitions function in PostgreSQL". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.