iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用
  • 342
分享到

PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用

2024-04-02 19:04:59 342人浏览 泡泡鱼
摘要

这篇文章将为大家详细讲解有关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函数怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用

本文链接: https://www.lsjlt.com/news/64733.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用
    这篇文章将为大家详细讲解有关PostgreSQL中prune_append_rel_partitions->get_matching_partitions函数怎么用,小编觉得挺实用的,因此分享给大家做...
    99+
    2024-04-02
  • PostgreSQL中heap_insert->XLogInsert函数分析
    本篇内容介绍了“PostgreSQL中heap_insert->XLogInsert函数分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
    99+
    2024-04-02
  • PostgreSQL中PortalRun->PortalRunSelect函数的实现逻辑是什么
    本篇内容介绍了“PostgreSQL中PortalRun->PortalRunSelect函数的实现逻辑是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带...
    99+
    2024-04-02
  • PostgreSQL物理优化中的create_index_paths->generate_bitmap_or_paths函数分析
    这篇文章主要讲解了“PostgreSQL物理优化中的create_index_paths->generate_bitmap_or_paths函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大...
    99+
    2024-04-02
  • 怎么使用PostgreSQL中ExecInitExprRec函数
    本篇内容主要讲解“怎么使用PostgreSQL中ExecInitExprRec函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用PostgreSQL中E...
    99+
    2024-04-02
  • postgresql中nullif函数怎么使用
    在 PostgreSQL 中,NULLIF 函数用于比较两个表达式,并在这两个表达式相等时返回 NULL 值。语法如下: NULLI...
    99+
    2024-05-08
    postgresql
  • PostgreSQL物理优化中的create_index_paths->choose_bitmap_and函数分析
    这篇文章主要讲解了“PostgreSQL物理优化中的create_index_paths->choose_bitmap_and函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思...
    99+
    2024-04-02
  • 怎么使用PostgreSQL ExecAgg函数
    本篇内容介绍了“怎么使用PostgreSQL ExecAgg函数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2024-04-02
  • PostgreSQL怎么调用mergeruns函数
    这篇文章主要介绍“PostgreSQL怎么调用mergeruns函数”,在日常操作中,相信很多人在PostgreSQL怎么调用mergeruns函数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2024-04-02
  • 怎么使用PostgreSQL的tuplesort_performsort函数
    本篇内容主要讲解“怎么使用PostgreSQL的tuplesort_performsort函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Postgr...
    99+
    2024-04-02
  • 怎么使用PostgreSQL扩展函数
    这篇文章主要讲解了“怎么使用PostgreSQL扩展函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用PostgreSQL扩展函数”吧!例子.&nb...
    99+
    2024-04-02
  • PostgreSQL中的日期/时间函数怎么用
    这篇文章给大家分享的是有关PostgreSQL中的日期/时间函数怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、获取当前时间select now()select current_timestam...
    99+
    2023-06-26
  • 怎么把JavaScript函数放到<body>中
    这篇文章主要讲解了“怎么把JavaScript函数放到<body>中”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么把JavaScript函数...
    99+
    2024-04-02
  • PostgreSQL中BufferAlloc函数有什么作用
    这篇文章主要介绍“PostgreSQL中BufferAlloc函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中BufferAlloc函数有什么作用问题上存在疑惑,小编查阅了各式资料,整理出...
    99+
    2024-04-02
  • PostgreSQL中hash_search_with_hash_value函数有什么作用
    本篇内容主要讲解“PostgreSQL中hash_search_with_hash_value函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Pos...
    99+
    2024-04-02
  • PostgreSQL中set_base_rel_pathlists函数有什么作用
    这篇文章主要介绍“PostgreSQL中set_base_rel_pathlists函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中set_base_rel_pathlists函数有什么作...
    99+
    2024-04-02
  • PostgreSQL中grouping_planner函数有什么作用
    这篇文章主要介绍“PostgreSQL中grouping_planner函数有什么作用”,在日常操作中,相信很多人在PostgreSQL中grouping_planner函数有什么作用问题上存在疑惑,小编查...
    99+
    2024-04-02
  • PostgreSQL中mdread函数有什么作用
    本篇内容主要讲解“PostgreSQL中mdread函数有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中mdread函数有什么作用...
    99+
    2024-04-02
  • PostgreSQL中RelationGetBufferForTuple函数有什么作用
    这篇文章主要讲解了“PostgreSQL中RelationGetBufferForTuple函数有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Po...
    99+
    2024-04-02
  • PostgreSQL中BufTableInsert函数有什么作用
    本篇内容介绍了“PostgreSQL中BufTableInsert函数有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作