PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用
这篇文章将为大家详细讲解有关PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
一、数据结构
PartitionScheme
分区方案,根据设计,分区方案只包含分区方法的一般属性(列表与范围、分区列的数量和每个分区列的类型信息),而不包含特定的分区边界信息。
typedef struct PartitionSchemeData
{
char strategy;
int16 partnatts;
Oid *partopfamily;
Oid *partopcintype;
Oid *partcollation;
//缓存有关分区键数据类型的信息。
int16 *parttyplen;
bool *parttypbyval;
//缓存有关分区比较函数的信息。
FmgrInfo *partsupfunc;
} PartitionSchemeData;
typedef struct PartitionSchemeData *PartitionScheme;
PartitionPruneXXX
执行Prune期间需要使用的数据结构,包括PartitionPruneStep/PartitionPruneStepOp/PartitionPruneCombineOp/PartitionPruneStepCombine
typedef struct PartitionPruneStep
{
NodeTag type;
int step_id;
} PartitionPruneStep;
typedef struct PartitionPruneStepOp
{
PartitionPruneStep step;
StrategyNumber opstrategy;
List *exprs;
List *cmpfns;
Bitmapset *nullkeys;
} PartitionPruneStepOp;
typedef enum PartitionPruneCombineOp
{
PARTPRUNE_COMBINE_UNION,
PARTPRUNE_COMBINE_INTERSECT
} PartitionPruneCombineOp;
typedef struct PartitionPruneStepCombine
{
PartitionPruneStep step;
PartitionPruneCombineOp combineOp;
List *source_stepids;
} PartitionPruneStepCombine;
//执行PartitionPruneStep步骤后的结果
typedef struct PruneStepResult
{
Bitmapset *bound_offsets;
bool scan_default;
bool scan_null;
} PruneStepResult;
二、源码解读
get_matching_partitions函数确定在分区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;
//没有pruning步骤,则视为保留所有分区
if (num_steps == 0)
{
Assert(context->nparts > 0);
return bms_add_range(NULL, 0, context->nparts - 1);
}
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));
}
}
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];//分区编号
if (partindex >= 0)
result = bms_add_member(result, partindex);
}
//如果需要,添加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;
}
static PruneStepResult *
perform_pruning_base_step(PartitionPruneContext *context,
PartitionPruneStepOp *opstep)
{
ListCell *lc1,
*lc2;
int keyno,
nvalues;
Datum values[PARTITION_MAX_KEYS];
FmgrInfo *partsupfunc;
int stateidx;
Assert(list_length(opstep->exprs) == list_length(opstep->cmpfns));
nvalues = 0;
lc1 = list_head(opstep->exprs);
lc2 = list_head(opstep->cmpfns);
for (keyno = 0; keyno < context->partnatts; keyno++)
{
if (bms_is_member(keyno, opstep->nullkeys))
continue;
if (keyno > nvalues && context->strategy == PARTITION_STRATEGY_RANGE)
break;
if (lc1 != NULL)//步骤的条件表达式不为NULL
{
Expr *expr;
Datum datum;
bool isnull;
expr = lfirst(lc1);
stateidx = PruneCxtStateIdx(context->partnatts,
opstep->step.step_id, keyno);
if (partkey_datum_from_expr(context, expr, stateidx,
&datum, &isnull))
{
Oid cmpfn;
if (isnull)
{
PruneStepResult *result;
result = (PruneStepResult *) palloc(sizeof(PruneStepResult));
result->bound_offsets = NULL;
result->scan_default = false;
result->scan_null = false;
return result;
}
//配置stepcmpfuncs(步骤比较函数)入口
cmpfn = lfirst_oid(lc2);
Assert(OidIsValid(cmpfn));
if (cmpfn != context->stepcmpfuncs[stateidx].fn_oid)
{
if (cmpfn == context->partsupfunc[keyno].fn_oid)
fmgr_info_copy(&context->stepcmpfuncs[stateidx],
&context->partsupfunc[keyno],
context->ppccontext);
else
fmgr_info_cxt(cmpfn, &context->stepcmpfuncs[stateidx],
context->ppccontext);
}
values[keyno] = datum;
nvalues++;
}
lc1 = lnext(lc1);
lc2 = lnext(lc2);
}
}
stateidx = PruneCxtStateIdx(context->partnatts, opstep->step.step_id, 0);
partsupfunc = &context->stepcmpfuncs[stateidx];
switch (context->strategy)
{
case PARTITION_STRATEGY_HASH:
return get_matching_hash_bounds(context,
opstep->opstrategy,
values, nvalues,
partsupfunc,
opstep->nullkeys);
case PARTITION_STRATEGY_LIST:
return get_matching_list_bounds(context,
opstep->opstrategy,
values[0], nvalues,
&partsupfunc[0],
opstep->nullkeys);
case PARTITION_STRATEGY_RANGE:
return get_matching_range_bounds(context,
opstep->opstrategy,
values, nvalues,
partsupfunc,
opstep->nullkeys);
default:
elog(ERROR, "unexpected partition strategy: %d",
(int) context->strategy);
break;
}
return NULL;
}
static PruneStepResult *
perform_pruning_combine_step(PartitionPruneContext *context,
PartitionPruneStepCombine *cstep,
PruneStepResult **step_results)
{
ListCell *lc1;
PruneStepResult *result = NULL;
bool firststep;
result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
if (list_length(cstep->source_stepids) == 0)
{
PartitionBoundInfo boundinfo = context->boundinfo;
result->bound_offsets = bms_add_range(NULL, 0, boundinfo->ndatums - 1);
result->scan_default = partition_bound_has_default(boundinfo);
result->scan_null = partition_bound_accepts_nulls(boundinfo);
return result;
}
switch (cstep->combineOp)//根据组合操作类型确定相应逻辑
{
case PARTPRUNE_COMBINE_UNION://PARTPRUNE_COMBINE_UNION
foreach(lc1, cstep->source_stepids)
{
int step_id = lfirst_int(lc1);
PruneStepResult *step_result;
if (step_id >= cstep->step.step_id)
elog(ERROR, "invalid pruning combine step argument");
step_result = step_results[step_id];
Assert(step_result != NULL);
//记录从该步骤产生的偏移索引
result->bound_offsets = bms_add_members(result->bound_offsets,
step_result->bound_offsets);
//更新扫描null/default分区的标记
if (!result->scan_null)
result->scan_null = step_result->scan_null;
if (!result->scan_default)
result->scan_default = step_result->scan_default;
}
break;
case PARTPRUNE_COMBINE_INTERSECT://PARTPRUNE_COMBINE_INTERSECT
firststep = true;
foreach(lc1, cstep->source_stepids)
{
int step_id = lfirst_int(lc1);
PruneStepResult *step_result;
if (step_id >= cstep->step.step_id)
elog(ERROR, "invalid pruning combine step argument");
step_result = step_results[step_id];
Assert(step_result != NULL);
if (firststep)//第一个步骤
{
//第一次,拷贝步骤的结果
result->bound_offsets =
bms_copy(step_result->bound_offsets);
result->scan_null = step_result->scan_null;
result->scan_default = step_result->scan_default;
firststep = false;
}
else
{
//记录其他步骤产生的索引
result->bound_offsets =
bms_int_members(result->bound_offsets,
step_result->bound_offsets);
//更新扫描null/default分区的标记
if (result->scan_null)
result->scan_null = step_result->scan_null;
if (result->scan_default)
result->scan_default = step_result->scan_default;
}
}
break;
}
return result;
}
static PruneStepResult *
get_matching_hash_bounds(PartitionPruneContext *context,
StrategyNumber opstrategy, Datum *values, int nvalues,
FmgrInfo *partsupfunc, Bitmapset *nullkeys)
{
PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
PartitionBoundInfo boundinfo = context->boundinfo;
int *partindices = boundinfo->indexes;
int partnatts = context->partnatts;
bool isnull[PARTITION_MAX_KEYS];
int i;
uint64 rowHash;
int greatest_modulus;
Assert(context->strategy == PARTITION_STRATEGY_HASH);
if (nvalues + bms_num_members(nullkeys) == partnatts)
{
Assert(opstrategy == HTEqualStrategyNumber || nvalues == 0);
for (i = 0; i < 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
{
//程序执行到这里,意味着至少存在一个hash分区
Assert(boundinfo->ndatums > 0);
result->bound_offsets = bms_add_range(NULL, 0,
boundinfo->ndatums - 1);
}
result->scan_null = result->scan_default = false;
return result;
}
三、跟踪分析
测试脚本如下
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)
启动gdb,设置断点
(gdb) b get_matching_partitions
Breakpoint 1 at 0x804d3b: file partprune.c, line 619.
(gdb) c
Continuing.
Breakpoint 1, get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:619
619 int num_steps = list_length(pruning_steps),
(gdb) n
626 if (num_steps == 0)
查看输入参数,pruning_steps是有3个ITEM的链表
(gdb) p *pruning_steps
$1 = {type = T_List, length = 3, head = 0x14d52d8, tail = 0x14d58d0}
pruning_steps的3个ITEM类型分别是PartitionPruneStepOp/PartitionPruneStepOp/PartitionPruneStepCombine
第1和2个ITEM的expr是Const,即常量1和2
(gdb) p *(Node *)pruning_steps->head->data.ptr_value
$2 = {type = T_PartitionPruneStepOp} -->Node类型
(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, length = 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} -->第1个步骤的表达式,常量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} -->第2个步骤的表达式,常量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} -->第3个步骤,组合操作是PARTPRUNE_COMBINE_UNION
为步骤结果分配内存
(gdb) n
640 palloc0(num_steps * sizeof(PruneStepResult *));
(gdb) p num_steps
$10 = 3
(gdb) n
639 results = (PruneStepResult **)
(gdb)
641 foreach(lc, pruning_steps)
开始遍历pruning步骤,进入perform_pruning_base_step函数
(gdb)
643 PartitionPruneStep *step = lfirst(lc);
(gdb)
645 switch (nodeTag(step))
(gdb)
648 results[step->step_id] =
(gdb) step
649 perform_pruning_base_step(context,
(gdb)
perform_pruning_base_step (context=0x7fff4a5e3930, opstep=0x14d4e98) at partprune.c:2995
2995 Assert(list_length(opstep->exprs) == list_length(opstep->cmpfns));
perform_pruning_base_step->查看输入参数,比较函数是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) n
2998 lc1 = list_head(opstep->exprs);
(gdb)
2999 lc2 = list_head(opstep->cmpfns);
(gdb)
perform_pruning_base_step->遍历分区键
(gdb)
3005 for (keyno = 0; keyno < context->partnatts; keyno++)
(gdb)
3012 if (bms_is_member(keyno, opstep->nullkeys)) -->没有null键
(gdb)
3019 if (keyno > nvalues && context->strategy == PARTITION_STRATEGY_RANGE) -->nvalues为0
(gdb) p nvalues
$17 = 0
(gdb) n
3022 if (lc1 != NULL)
(gdb)
3028 expr = lfirst(lc1); -->获取步骤中的表达式,其实是常量1
(gdb)
3029 stateidx = PruneCxtStateIdx(context->partnatts, -->stateidx为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) n
3031 if (partkey_datum_from_expr(context, expr, stateidx,
(gdb) p stateidx
$20 = 0
(gdb) n
3041 if (isnull) -->非NULL
(gdb) p isnull
$21 = false
perform_pruning_base_step->获取比较函数进行处理
(gdb) n
3054 cmpfn = lfirst_oid(lc2); --> OID=425
(gdb)
3055 Assert(OidIsValid(cmpfn));
(gdb)
3056 if (cmpfn != context->stepcmpfuncs[stateidx].fn_oid) -->fn_oid为0
(gdb)
3064 if (cmpfn == context->partsupfunc[keyno].fn_oid) -->fn_oid为425
(gdb) p context->stepcmpfuncs[stateidx].fn_oid
$22 = 0
(gdb) p context->partsupfunc[keyno].fn_oid
$23 = 425
(gdb) n
3065 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], --> 拷贝函数
(gdb)
3073 values[keyno] = datum;-->设置值
(gdb) p datum
$24 = 1
(gdb) n
3074 nvalues++;
(gdb)
3077 lc1 = lnext(lc1);
(gdb)
3078 lc2 = lnext(lc2);
(gdb)
perform_pruning_base_step->完成分区键遍历
(gdb) n
3005 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->进入get_matching_hash_bounds函数
(gdb)
3092 return get_matching_hash_bounds(context,
(gdb) step
3093 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:2156
2156 PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
(gdb)
get_matching_hash_bounds->变量赋值
(gdb) n
2157 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->分区边界信息,共有6个分区,Index分别是0-5
(gdb) p boundinfo
$25 = (PartitionBoundInfo) 0x14d32a0
(gdb) p *boundinfo
$26 = {strategy = 104 'h', 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->indexes
Cannot 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->分区索引和分区键数
(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->遍历分区键,判断值是否落在分区中
(gdb) n
2178 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 --> 约束条件
(gdb) p isnull[0]
$38 = false -->不为NULL
(gdb) p greatest_modulus
$39 = 6 -->6个分区
(gdb) p rowHash
$40 = 11274504255086170040 -->values算出的Hash值
(gdb) p rowHash % greatest_modulus
$41 = 2 --> 所在的分区
(gdb) p partindices[2]
$42 = 2 -->存在该分区
(gdb)
get_matching_hash_bounds->返回结果(bound_offsets->words=4,即编号2)
(gdb) n
2189 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)
回到get_matching_partitions
(gdb) n
perform_pruning_base_step (context=0x7fff4a5e3930, opstep=0x14d4e98) at partprune.c:3119
3119 }
(gdb)
get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:648
648 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
继续执行步骤,进入perform_pruning_combine_step
654 results[step->step_id] =
(gdb)
655 perform_pruning_combine_step(context,
(gdb) step
perform_pruning_combine_step (context=0x7fff4a5e3930, cstep=0x14d5898, step_results=0x14d5958) at partprune.c:3136
3136 PruneStepResult *result = NULL;
(gdb)
perform_pruning_combine_step->进入PARTPRUNE_COMBINE_UNION处理逻辑
(gdb) n
3143 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->遍历组合步骤的源步骤 cstep->source_stepids,合并这些步骤的结果
(gdb) n
3159 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->最终结果
(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->回到get_matching_partitions
(gdb) n
3224 }
(gdb)
get_matching_partitions (context=0x7fff4a5e3930, pruning_steps=0x14d5300) at partprune.c:654
654 results[step->step_id] =
完成所有步骤的处理
(gdb) n
658 break;
(gdb)
641 foreach(lc, pruning_steps)
(gdb) n
671 final_result = results[num_steps - 1];
(gdb)
672 Assert(final_result != NULL);
(gdb)
构造结果位图集
...
675 while ((i = bms_next_member(final_result->bound_offsets, i)) >= 0)
(gdb) n
677 int partindex = context->boundinfo->indexes[i];
(gdb)
687 if (partindex >= 0)
(gdb)
688 result = bms_add_member(result, partindex);
(gdb)
完成调用
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)
关于“PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341