溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

PostgreSQL聚合函數(shù)的實(shí)現(xiàn)方法是什么

發(fā)布時(shí)間:2021-11-09 13:52:57 來(lái)源:億速云 閱讀:174 作者:iii 欄目:關(guān)系型數(shù)據(jù)庫(kù)

本篇內(nèi)容介紹了“PostgreSQL聚合函數(shù)的實(shí)現(xiàn)方法是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

一、數(shù)據(jù)結(jié)構(gòu)

AggState
聚合函數(shù)執(zhí)行時(shí)狀態(tài)結(jié)構(gòu)體,內(nèi)含AggStatePerAgg等結(jié)構(gòu)體

/* ---------------------
 *    AggState information
 *
 *    ss.ss_ScanTupleSlot refers to output of underlying plan.
 *  ss.ss_ScanTupleSlot指的是基礎(chǔ)計(jì)劃的輸出.
 *    (ss = ScanState,ps = PlanState)
 *
 *    Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
 *    ecxt_aggnulls arrays, which hold the computed agg values for the current
 *    input group during evaluation of an Agg node's output tuple(s).  We
 *    create a second ExprContext, tmpcontext, in which to evaluate input
 *    expressions and run the aggregate transition functions.
 *    注意:ss.ps.ps_ExprContext包含了ecxt_aggvalues和ecxt_aggnulls數(shù)組,
 *      這兩個(gè)數(shù)組保存了在計(jì)算agg節(jié)點(diǎn)的輸出元組時(shí)當(dāng)前輸入組已計(jì)算的agg值.
 * ---------------------
 */
/* these structs are private in nodeAgg.c: */
//在nodeAgg.c中私有的結(jié)構(gòu)體
typedef struct AggStatePerAggData *AggStatePerAgg;
typedef struct AggStatePerTransData *AggStatePerTrans;
typedef struct AggStatePerGroupData *AggStatePerGroup;
typedef struct AggStatePerPhaseData *AggStatePerPhase;
typedef struct AggStatePerHashData *AggStatePerHash;
typedef struct AggState
{
    //第一個(gè)字段是NodeTag(繼承自ScanState)
    ScanState    ss;                /* its first field is NodeTag */
    //targetlist和quals中所有的Aggref
    List       *aggs;            /* all Aggref nodes in targetlist & quals */
    //鏈表的大小(可以為0)
    int            numaggs;        /* length of list (could be zero!) */
    //pertrans條目大小
    int            numtrans;        /* number of pertrans items */
    //Agg策略模式
    AggStrategy aggstrategy;    /* strategy mode */
    //agg-splitting模式,參見(jiàn)nodes.h
    AggSplit    aggsplit;        /* agg-splitting mode, see nodes.h */
    //指向當(dāng)前步驟數(shù)據(jù)的指針
    AggStatePerPhase phase;        /* pointer to current phase data */
    //步驟數(shù)(包括0)
    int            numphases;        /* number of phases (including phase 0) */
    //當(dāng)前步驟
    int            current_phase;    /* current phase number */
    //per-Aggref信息
    AggStatePerAgg peragg;        /* per-Aggref information */
    //per-Trans狀態(tài)信息
    AggStatePerTrans pertrans;    /* per-Trans state information */
    //長(zhǎng)生命周期數(shù)據(jù)的ExprContexts(hashtable)
    ExprContext *hashcontext;    /* econtexts for long-lived data (hashtable) */
    ////長(zhǎng)生命周期數(shù)據(jù)的ExprContexts(每一個(gè)GS使用)
    ExprContext **aggcontexts;    /* econtexts for long-lived data (per GS) */
    //輸入表達(dá)式的ExprContext
    ExprContext *tmpcontext;    /* econtext for input expressions */
#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
    //當(dāng)前活躍的aggcontext
    ExprContext *curaggcontext; /* currently active aggcontext */
    //當(dāng)前活躍的aggregate(如存在)
    AggStatePerAgg curperagg;    /* currently active aggregate, if any */
#define FIELDNO_AGGSTATE_CURPERTRANS 16
    //當(dāng)前活躍的trans state
    AggStatePerTrans curpertrans;    /* currently active trans state, if any */
    //輸入結(jié)束?
    bool        input_done;        /* indicates end of input */
    //Agg掃描結(jié)束?
    bool        agg_done;        /* indicates completion of Agg scan */
    //最后一個(gè)grouping set
    int            projected_set;    /* The last projected grouping set */
#define FIELDNO_AGGSTATE_CURRENT_SET 20
    //將要解析的當(dāng)前grouping set
    int            current_set;    /* The current grouping set being evaluated */
    //當(dāng)前投影操作的分組列
    Bitmapset  *grouped_cols;    /* grouped cols in current projection */
    //倒序的分組列鏈表
    List       *all_grouped_cols;    /* list of all grouped cols in DESC order */
    /* These fields are for grouping set phase data */
    //-------- 下面的列用于grouping set步驟數(shù)據(jù)
    //所有步驟中最大的sets大小
    int            maxsets;        /* The max number of sets in any phase */
    //所有步驟的數(shù)組
    AggStatePerPhase phases;    /* array of all phases */
    //對(duì)于phases > 1,已排序的輸入信息
    Tuplesortstate *sort_in;    /* sorted input to phases > 1 */
    //對(duì)于下一個(gè)步驟,輸入已拷貝
    Tuplesortstate *sort_out;    /* input is copied here for next phase */
    //排序結(jié)果的slot
    TupleTableSlot *sort_slot;    /* slot for sort results */
    /* these fields are used in AGG_PLAIN and AGG_SORTED modes: */
    //------- 下面的列用于A(yíng)GG_PLAIN和AGG_SORTED模式:
    //per-group指針的grouping set編號(hào)數(shù)組
    AggStatePerGroup *pergroups;    /* grouping set indexed array of per-group
                                     * pointers */
    //當(dāng)前組的第一個(gè)元組拷貝
    HeapTuple    grp_firstTuple; /* copy of first tuple of current group */
    /* these fields are used in AGG_HASHED and AGG_MIXED modes: */
    //--------- 下面的列用于A(yíng)GG_HASHED和AGG_MIXED模式:
    //是否已填充hash表?
    bool        table_filled;    /* hash table filled yet? */
    //hash桶數(shù)?
    int            num_hashes;
    //相應(yīng)的哈希表數(shù)據(jù)數(shù)組
    AggStatePerHash perhash;    /* array of per-hashtable data */
    //per-group指針的grouping set編號(hào)數(shù)組
    AggStatePerGroup *hash_pergroup;    /* grouping set indexed array of
                                         * per-group pointers */
    /* support for evaluation of agg input expressions: */
    //---------- agg輸入表達(dá)式解析支持
#define FIELDNO_AGGSTATE_ALL_PERGROUPS 34
    //首先是->pergroups,然后是hash_pergroup
    AggStatePerGroup *all_pergroups;    /* array of first ->pergroups, than
                                         * ->hash_pergroup */
    //投影實(shí)現(xiàn)機(jī)制
    ProjectionInfo *combinedproj;    /* projection machinery */
} AggState;
/* Primitive options supported by nodeAgg.c: */
//nodeag .c支持的基本選項(xiàng)
#define AGGSPLITOP_COMBINE        0x01    /* substitute combinefn for transfn */
#define AGGSPLITOP_SKIPFINAL    0x02    /* skip finalfn, return state as-is */
#define AGGSPLITOP_SERIALIZE    0x04    /* apply serializefn to output */
#define AGGSPLITOP_DESERIALIZE    0x08    /* apply deserializefn to input */
/* Supported operating modes (i.e., useful combinations of these options): */
//支持的操作模式
typedef enum AggSplit
{
    /* Basic, non-split aggregation: */
    //基本 : 非split聚合
    AGGSPLIT_SIMPLE = 0,
    /* Initial phase of partial aggregation, with serialization: */
    //部分聚合的初始步驟,序列化
    AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
    /* Final phase of partial aggregation, with deserialization: */
    //部分聚合的最終步驟,反序列化
    AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
} AggSplit;
/* Test whether an AggSplit value selects each primitive option: */
//測(cè)試AggSplit選擇了哪些基本選項(xiàng)
#define DO_AGGSPLIT_COMBINE(as)        (((as) & AGGSPLITOP_COMBINE) != 0)
#define DO_AGGSPLIT_SKIPFINAL(as)    (((as) & AGGSPLITOP_SKIPFINAL) != 0)
#define DO_AGGSPLIT_SERIALIZE(as)    (((as) & AGGSPLITOP_SERIALIZE) != 0)
#define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0)

二、源碼解讀

N/A

三、跟蹤分析

跟蹤分析數(shù)據(jù)結(jié)構(gòu)中的相關(guān)信息.
測(cè)試數(shù)據(jù):

-- 禁用并行
set max_parallel_workers_per_gather=0;
select bh,avg(c1),min(c1),max(c2) from t_agg_simple group by bh;

aggstate是聚合運(yùn)算的運(yùn)行狀態(tài).

1536        AggState   *node = castNode(AggState, pstate);
(gdb) n
1537        TupleTableSlot *result = NULL;
(gdb) p *node
$1 = {ss = {ps = {type = T_AggState, plan = 0x120ba30, state = 0x12eb428, ExecProcNode = 0x6ee438 <ExecAgg>, 
      ExecProcNodeReal = 0x6ee438 <ExecAgg>, instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, 
      qual = 0x0, lefttree = 0x12ebbb0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, 
      ps_ResultTupleSlot = 0x12ec7b0, ps_ExprContext = 0x12ebaf0, ps_ProjInfo = 0x12ec8f0, scandesc = 0x12ebf00}, 
    ss_currentRelation = 0x0, ss_currentScanDesc = 0x0, ss_ScanTupleSlot = 0x12ec458}, aggs = 0x12ece00, numaggs = 3, 
  numtrans = 3, aggstrategy = AGG_HASHED, aggsplit = AGGSPLIT_SIMPLE, phase = 0x12ecef8, numphases = 1, current_phase = 0, 
  peragg = 0x13083e0, pertrans = 0x130a3f0, hashcontext = 0x12eba30, aggcontexts = 0x12eb858, tmpcontext = 0x12eb878, 
  curaggcontext = 0x12eba30, curperagg = 0x0, curpertrans = 0x0, input_done = false, agg_done = false, projected_set = -1, 
  current_set = 0, grouped_cols = 0x0, all_grouped_cols = 0x12ed090, maxsets = 1, phases = 0x12ecef8, sort_in = 0x0, 
  sort_out = 0x0, sort_slot = 0x0, pergroups = 0x0, grp_firstTuple = 0x0, table_filled = false, num_hashes = 1, 
  perhash = 0x12ecf50, hash_pergroup = 0x13085f8, all_pergroups = 0x13085f8, combinedproj = 0x0}

aggstate->phase/phases是當(dāng)前階段/所有階段的信息.
在本例中,由于只有一個(gè)階段:AGG_HASHED,因此兩者是一樣的.

(gdb) p *node->phase
$2 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x12ecfe8, grouped_cols = 0x12ed008, eqfunctions = 0x0, 
  aggnode = 0x120ba30, sortnode = 0x0, evaltrans = 0x1315800}
(gdb) p node->phases[0]
$27 = {aggstrategy = AGG_HASHED, numsets = 1, gset_lengths = 0x12ecfe8, grouped_cols = 0x12ed008, eqfunctions = 0x0, 
  aggnode = 0x120ba30, sortnode = 0x0, evaltrans = 0x1315800}

aggstate->phase->evaltrans是該階段的表達(dá)式解析轉(zhuǎn)換函數(shù).
在本例中,該函數(shù)是ExecInterpExpr(通過(guò)執(zhí)行一系列的步驟得到值)

(gdb) p *node->phase->evaltrans
$3 = {tag = {type = T_ExprState}, flags = 6 '\006', resnull = false, resvalue = 0, resultslot = 0x0, steps = 0x1315ac0, 
  evalfunc = 0x6cd882 <ExecInterpExprStillValid>, expr = 0x12eb640, evalfunc_private = 0x6cb43e <ExecInterpExpr>, 
  steps_len = 16, steps_alloc = 16, parent = 0x12eb640, ext_params = 0x0, innermost_caseval = 0x0, 
  innermost_casenull = 0x0, innermost_domainval = 0x0, innermost_domainnull = 0x0}

aggstate->phase->evaltrans是該階段的聚合節(jié)點(diǎn),即T_AGG.

(gdb) p *node->phase->aggnode
$9 = {plan = {type = T_Agg, startup_cost = 24.800000000000001, total_cost = 27.300000000000001, plan_rows = 200, 
    plan_width = 98, parallel_aware = false, parallel_safe = false, plan_node_id = 0, targetlist = 0x12fbf10, qual = 0x0, 
    lefttree = 0x12fb9d0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, aggstrategy = AGG_HASHED, 
  aggsplit = AGGSPLIT_SIMPLE, numCols = 1, grpColIdx = 0x12fbcc0, grpOperators = 0x12fbca0, numGroups = 200, 
  aggParams = 0x0, groupingSets = 0x0, chain = 0x0}

aggstate->peragg存儲(chǔ)的是per-Aggref信息,亦即每一個(gè)聚合對(duì)應(yīng)一個(gè),每一個(gè)peragg->aggref對(duì)應(yīng)一個(gè)聚合信息.
第1個(gè)是max:

(gdb) p *node->peragg
$10 = {aggref = 0x12fc458, transno = 0, finalfn_oid = 0, finalfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, 
    fn_strict = false, fn_retset = false, fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, 
  numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen = 4, resulttypeByVal = true, shareable = true}
(gdb) p *node->peragg->aggref
$11 = {xpr = {type = T_Aggref}, aggfnoid = 2116, aggtype = 23, aggcollid = 0, inputcollid = 0, aggtranstype = 23, 
  aggargtypes = 0x12fc518, aggdirectargs = 0x0, args = 0x12fc628, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, 
  aggstar = false, aggvariadic = false, aggkind = 110 'n', agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 26}
########  
testdb=# select oid,proname from pg_proc where oid in (2116,768);
 oid  |  proname   
------+------------
  768 | int4larger
 2116 | max
(2 rows)
########

第2個(gè)是min:

(gdb) p node->peragg[1]
$38 = {aggref = 0x12fc1d0, transno = 1, finalfn_oid = 0, finalfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, 
    fn_strict = false, fn_retset = false, fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, 
  numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen = 4, resulttypeByVal = true, shareable = true}
(gdb) p *node->peragg[1]->aggref
$39 = {xpr = {type = T_Aggref}, aggfnoid = 2132, aggtype = 23, aggcollid = 0, inputcollid = 0, aggtranstype = 23, 
  aggargtypes = 0x12fc290, aggdirectargs = 0x0, args = 0x12fc3a0, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, 
  aggstar = false, aggvariadic = false, aggkind = 110 'n', agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 18}
############
testdb=# select oid,proname from pg_proc where oid in (2132,769);
 oid  |   proname   
------+-------------
  769 | int4smaller
 2132 | min
(2 rows)
###########

第3個(gè)是avg:

(gdb) p node->peragg[2]
$40 = {aggref = 0x12fbf48, transno = 2, finalfn_oid = 1964, finalfn = {fn_addr = 0x978251 <int8_avg>, fn_oid = 1964, 
    fn_nargs = 1, fn_strict = true, fn_retset = false, fn_stats = 2 '\002', fn_extra = 0x0, fn_mcxt = 0x12eb310, 
    fn_expr = 0x1315698}, numFinalArgs = 1, aggdirectargs = 0x0, resulttypeLen = -1, resulttypeByVal = false, 
  shareable = true}
(gdb) p *node->peragg[2]->aggref
$41 = {xpr = {type = T_Aggref}, aggfnoid = 2101, aggtype = 1700, aggcollid = 0, inputcollid = 0, aggtranstype = 1016, 
  aggargtypes = 0x12fc008, aggdirectargs = 0x0, args = 0x12fc118, aggorder = 0x0, aggdistinct = 0x0, aggfilter = 0x0, 
  aggstar = false, aggvariadic = false, aggkind = 110 'n', agglevelsup = 0, aggsplit = AGGSPLIT_SIMPLE, location = 10}
#####
testdb=# select oid,proname from pg_proc where oid in (2101,1963);
 oid  |    proname     
------+----------------
 1963 | int4_avg_accum
 2101 | avg
(2 rows)
#####

aggstate->pertrans保存的是轉(zhuǎn)換函數(shù).
第1/2/3個(gè)分別是int4larger/int4smaller/int4_avg_accum

(gdb) p node->pertrans[0]
$19 = {aggref = 0x12fc458, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 768, serialfn_oid = 0, 
  deserialfn_oid = 0, aggtranstype = 23, transfn = {fn_addr = 0x93e877 <int4larger>, fn_oid = 768, fn_nargs = 2, 
    fn_strict = true, fn_retset = false, fn_stats = 2 '\002', fn_extra = 0x0, fn_mcxt = 0x12eb310, fn_expr = 0x1315458}, 
  serialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0 '\000', 
    fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, 
    fn_strict = false, fn_retset = false, fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, 
  aggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0, sortOperators = 0x0, sortCollations = 0x0, 
  sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, 
    fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 0, 
  initValueIsNull = true, inputtypeLen = 0, transtypeLen = 4, inputtypeByVal = false, transtypeByVal = true, 
  sortslot = 0x0, uniqslot = 0x0, sortdesc = 0x0, sortstates = 0x1308620, transfn_fcinfo = {flinfo = 0x130a418, 
    context = 0x12eb640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0 <repeats 100 times>}, 
    argnull = {false <repeats 100 times>}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, 
    fncollation = 0, isnull = false, nargs = 0, arg = {0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}, 
  deserialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {
      0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}}
(gdb) p node->pertrans[1]
$20 = {aggref = 0x12fc1d0, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 769, serialfn_oid = 0, 
  deserialfn_oid = 0, aggtranstype = 23, transfn = {fn_addr = 0x93e8a3 <int4smaller>, fn_oid = 769, fn_nargs = 2, 
    fn_strict = true, fn_retset = false, fn_stats = 2 '\002', fn_extra = 0x0, fn_mcxt = 0x12eb310, fn_expr = 0x13155a8}, 
  serialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0 '\000', 
    fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, 
    fn_strict = false, fn_retset = false, fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, 
  aggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0, sortOperators = 0x0, sortCollations = 0x0, 
  sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, 
    fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 0, 
  initValueIsNull = true, inputtypeLen = 0, transtypeLen = 4, inputtypeByVal = false, transtypeByVal = true, 
  sortslot = 0x0, uniqslot = 0x0, sortdesc = 0x0, sortstates = 0x1308640, transfn_fcinfo = {flinfo = 0x130b060, 
    context = 0x12eb640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0 <repeats 100 times>}, 
    argnull = {false <repeats 100 times>}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, 
    fncollation = 0, isnull = false, nargs = 0, arg = {0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}, 
  deserialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {
      0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}}
(gdb) p node->pertrans[2]
$21 = {aggref = 0x12fbf48, aggshared = false, numInputs = 1, numTransInputs = 1, transfn_oid = 1963, serialfn_oid = 0, 
  deserialfn_oid = 0, aggtranstype = 1016, transfn = {fn_addr = 0x977d8f <int4_avg_accum>, fn_oid = 1963, fn_nargs = 2, 
    fn_strict = true, fn_retset = false, fn_stats = 2 '\002', fn_extra = 0x0, fn_mcxt = 0x12eb310, fn_expr = 0x1315a68}, 
  serialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, fn_stats = 0 '\000', 
    fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, deserialfn = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, 
    fn_strict = false, fn_retset = false, fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, 
  aggCollation = 0, numSortCols = 0, numDistinctCols = 0, sortColIdx = 0x0, sortOperators = 0x0, sortCollations = 0x0, 
  sortNullsFirst = 0x0, equalfnOne = {fn_addr = 0x0, fn_oid = 0, fn_nargs = 0, fn_strict = false, fn_retset = false, 
    fn_stats = 0 '\000', fn_extra = 0x0, fn_mcxt = 0x0, fn_expr = 0x0}, equalfnMulti = 0x0, initValue = 20010920, 
  initValueIsNull = false, inputtypeLen = 0, transtypeLen = -1, inputtypeByVal = false, transtypeByVal = false, 
  sortslot = 0x0, uniqslot = 0x0, sortdesc = 0x0, sortstates = 0x13156f0, transfn_fcinfo = {flinfo = 0x130bca8, 
    context = 0x12eb640, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {0 <repeats 100 times>}, 
    argnull = {false <repeats 100 times>}}, serialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, 
    fncollation = 0, isnull = false, nargs = 0, arg = {0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}, 
  deserialfn_fcinfo = {flinfo = 0x0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 0, arg = {
      0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}}

aggstate->perhash存儲(chǔ)的是per-hashtable數(shù)據(jù).perhash->hashslot存儲(chǔ)的是最小化Tuple.
本例只有一個(gè)group set,因此對(duì)應(yīng)的hash表只有一個(gè).

(gdb) p node->perhash[0]
$30 = {hashtable = 0x1308890, hashiter = {cur = 0, end = 0, done = false}, hashslot = 0x12ed238, hashfunctions = 0x12ed2d0, 
  eqfuncoids = 0x1308700, numCols = 1, numhashGrpCols = 1, largestGrpColIdx = 1, hashGrpColIdxInput = 0x1308660, 
  hashGrpColIdxHash = 0x1308680, aggnode = 0x120ba30}
(gdb) p node->perhash[0]->hashslot[0]
$32 = {type = T_TupleTableSlot, tts_isempty = true, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, 
  tts_tuple = 0x0, tts_tupleDescriptor = 0x12ed120, tts_mcxt = 0x12eb310, tts_buffer = 0, tts_nvalid = 0, 
  tts_values = 0x12ed298, tts_isnull = 0x12ed2a0, tts_mintuple = 0x0, tts_minhdr = {t_len = 0, t_self = {ip_blkid = {
        bi_hi = 0, bi_lo = 0}, ip_posid = 0}, t_tableOid = 0, t_data = 0x0}, tts_off = 0, tts_fixedTupleDescriptor = true}

其他的數(shù)據(jù)結(jié)構(gòu).
aggstate->hash_pergroup/all_pergroups/combinedproj

(gdb) p node->hash_pergroup
$35 = (AggStatePerGroup *) 0x13085f8
(gdb) p *node->hash_pergroup
$36 = (AggStatePerGroup) 0x0
(gdb) p *node->all_pergroups
$37 = (AggStatePerGroup) 0x0
(gdb) p *node->combinedproj
Cannot access memory at address 0x0

簡(jiǎn)單來(lái)說(shuō),整個(gè)過(guò)程大體如下:
每個(gè)Group的列信息會(huì)存儲(chǔ)在aggstate->perhash中,按階段(aggstate->phases)逐個(gè)執(zhí)行.
掃描數(shù)據(jù)表,在遍歷tuple的時(shí)候,通過(guò)hash函數(shù)比對(duì)(Key為最小化tuple)找到/創(chuàng)建相應(yīng)的Group組aggstate->perhash(hash table),提取tuple中相應(yīng)的列值作為參數(shù)輸入到aggstate->pertrans中定義的轉(zhuǎn)換函數(shù)中,解析執(zhí)行結(jié)果并存儲(chǔ),最后執(zhí)行投影操作,把最終結(jié)果返回給客戶(hù)端

“PostgreSQL聚合函數(shù)的實(shí)現(xiàn)方法是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI