PostgreSQL中prune

72次阅读
没有评论

共计 8954 个字符,预计需要花费 23 分钟才能阅读完成。

行业资讯    
数据库    
关系型数据库    
PostgreSQL 中 prune_append_rel_partitions- get_matching_partitions 函数怎么用

这篇文章将为大家详细讲解有关 PostgreSQL 中 prune_append_rel_partitions- get_matching_partitions 函数怎么用,丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、数据结构

PartitionScheme
分区方案, 根据设计,分区方案只包含分区方法的一般属性(列表与范围、分区列的数量和每个分区列的类型信息),而不包含特定的分区边界信息。

/*
 * 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.
 *  如果多个关系以相同的方式分区,那么所有这些分区都将具有指向相同 PartitionScheme 的指针。 * PartitionScheme 对象的链表附加到 PlannerInfo 中。 *  根据设计,分区方案只包含分区方法的一般属性(列表与范围、分区列的数量和每个分区列的类型信息), *  而不包含特定的界限。 *
 * We store the opclass-declared input data types 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.
 *  我们存储 opclass-declared 的输入数据类型,而不是分区键数据类型, *  因为前者用于比较分区边界,而不是后者。 *  由于分区键数据类型和 opclass-declared 的输入数据类型预期是二进制兼容的(每个 ResolveOpClass), *  所以它们应该具有相同的 byval 和 length 属性。 */
typedef struct PartitionSchemeData
 char strategy; /*  分区策略;partition strategy */
 int16 partnatts; /*  分区属性个数;number of partition attributes */
 Oid *partopfamily; /*  操作符族 OIDs;OIDs of operator families */
 Oid *partopcintype; /* opclass 声明的输入数据类型的 OIDs;OIDs of opclass declared input data types */
 Oid *partcollation; /*  分区排序规则 OIDs;OIDs of partitioning collations */
 /* Cached information about partition key data types. */
 // 缓存有关分区键数据类型的信息。 int16 *parttyplen;
 bool *parttypbyval;
 /* Cached information about partition comparison functions. */
 // 缓存有关分区比较函数的信息。 FmgrInfo *partsupfunc;
} PartitionSchemeData;
typedef struct PartitionSchemeData *PartitionScheme;

PartitionPruneXXX
执行 Prune 期间需要使用的数据结构, 包括 PartitionPruneStep/PartitionPruneStepOp/PartitionPruneCombineOp/PartitionPruneStepCombine

/*
 * Abstract Node type for partition pruning steps (there are no concrete
 * Nodes of this type).
 *  用于分区修剪步骤 pruning 的抽象节点类型(没有这种类型的具体节点)。 * 
 * step_id is the global identifier of the step within its pruning context.
 * step_id 是步骤在其修剪 pruning 上下文中的全局标识符。 */
typedef struct PartitionPruneStep
 NodeTag type;
 int step_id;
} PartitionPruneStep;
 /*
 * PartitionPruneStepOp - Information to prune using a set of mutually AND d
 * OpExpr clauses
 * PartitionPruneStepOp -  使用一组 AND 操作的 OpExpr 条件子句进行修剪 prune 的信息
 *
 * 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.
 *  它包含从 partnatts OpExpr 子句中提取的信息, *  其中 partnatts 是分区键列的数量。 * “opstrategy”是子句中与最后一个分区键匹配的操作符的策略。 *  exprs 包含一些表达式,这些表达式包含要传递给分区绑定搜索函数的查找键。 * “cmpfns”包含用于比较上述表达式与分区边界的比较函数的 OIDs。 * “exprs”和“cmpfns”包含相同数量的条目,最多包含 partnatts 个条目。 *
 * 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.
 *  一旦我们使用查找键找到分区绑定的偏移量, *  我们将根据“opstrategy”的值确定在结果中包含哪些分区。 *  例如,如果它是相等的,我们只返回包含该键的分区,或者如果该键不包含所有分区列, *  则返回一组分区。 *  对于非等值的情况,需要适当地包括其他分区。 *
 *  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 NULL 子句匹配的分区键 (0 到 partnatts - 1) 偏移量的集合。 *  这只适用于哈希分区,因为我们需要将哪些键为 null 传递给哈希分区绑定搜索函数。 *  对于给定的分区键和“nullkeys”中设置的相应 bit,不可能在“exprs”中出现表达式。 */
typedef struct PartitionPruneStepOp
 PartitionPruneStep step;
 StrategyNumber opstrategy;
 List *exprs;
 List *cmpfns;
 Bitmapset *nullkeys;
} PartitionPruneStepOp;
 * PartitionPruneStepCombine - Information to prune using a BoolExpr clause
 * PartitionPruneStepCombine -  使用 BoolExpr 条件 prune 的信息
 *
 * For BoolExpr clauses, we combine the set of partitions determined for each
 * of the argument clauses.
 *  对于 BoolExpr 子句,我们为每个参数子句确定的分区集进行组合。 */
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 */ // 执行 PartitionPruneStep 步骤后的结果 typedef struct PruneStepResult  /*  * The offsets of bounds (in a table s boundinfo) whose partition is  * selected by the pruning step.  *  被 pruning 步骤选中的分区边界 (在数据表 boundinfo 中) 偏移  */  Bitmapset *bound_offsets;  bool scan_default; /*  是否扫描默认分区? Scan the default partition? */  bool scan_null; /*  是否为 NULL 值扫描分区? Scan the partition for NULL values? */ } PruneStepResult;

二、源码解读

get_matching_partitions 函数确定在分区 pruning 后仍然 存活 的分区。

 /*
 * get_matching_partitions
 * Determine partitions that survive partition pruning
 *  确定在分区修剪 pruning 后仍然存在的分区.
 *
 * Returns a Bitmapset of the RelOptInfo- part_rels indexes of the surviving
 * partitions.
 *  返回 pruning 后仍存在的分区的 RelOptInfo- part_rels 索引位图集。
 */
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. */
 // 没有 pruning 步骤, 则视为保留所有分区
 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. 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.
 *  为单个修剪步骤分配空间来存储结果。
 *  每个 slot 将持有 pruning 后,执行一个给定的 pruning 步骤。
 *  后面的步骤可以使用前面一个或多个步骤的结果。
 *  应用所有步骤的结果是最后一个步骤的 slot 中包含的值。
 */
 results = (PruneStepResult **)
 palloc0(num_steps * sizeof(PruneStepResult *));
 foreach(lc, pruning_steps)// 遍历步骤
 {
 PartitionPruneStep *step = lfirst(lc);
 switch (nodeTag(step))
 {
 case T_PartitionPruneStepOp:
 results[step- step_id] =
 perform_pruning_base_step(context,
 (PartitionPruneStepOp *) step);// 执行 pruning 基础步骤
 break;
 case T_PartitionPruneStepCombine:
 results[step- step_id] =
 perform_pruning_combine_step(context,
 (PartitionPruneStepCombine *) step,
 results);// 执行 pruning 组合步骤
 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.
 *  到目前为止, 我们已经知道结果中需要的相应分区的所有数据的偏移量,
 *  包括特殊的接受 null 的分区和默认分区。
 *  现在收集实际的分区索引。
 */
 final_result = results[num_steps - 1];// 最终结果
 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];// 分区编号
 /*
 * 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.
 *  范围分区和散列分区,一些 slot 可能包含 -1,
 *  这表示没有定义接受给定范围的数据或给定余数的分区。
 *  在范围分区的情况下,默认分区 (如果有的话) 将被添加到结果中,
 *  因为指定的范围仍然满足查询的条件。
 */
 if (partindex  = 0)
 result = bms_add_member(result, partindex);
 }
 /* Add the null and/or default partition if needed and if present. */
 // 如果需要,添加 NULL 和 / 或默认分区。
 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;

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-24发表,共计8954字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)