这篇文章主要讲解了“PostgreSQL执行聚合函数所使用的数据结构有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL执行聚合函数所使用的数据结构有哪些”吧!

一、数据结构

AggState
聚合函数执行时状态结构体,内含AggStatePerAgg等结构体

/*---------------------*AggStateinformation**ss.ss_ScanTupleSlotreferstooutputofunderlyingplan.*ss.ss_ScanTupleSlot指的是基础计划的输出.*(ss=ScanState,ps=PlanState)**Note:ss.ps.ps_ExprContextcontainsecxt_aggvaluesand*ecxt_aggnullsarrays,whichholdthecomputedaggvaluesforthecurrent*inputgroupduringevaluationofanAggnode'soutputtuple(s).We*createasecondExprContext,tmpcontext,inwhichtoevaluateinput*expressionsandruntheaggregatetransitionfunctions.*注意:ss.ps.ps_ExprContext包含了ecxt_aggvalues和ecxt_aggnulls数组,*这两个数组保存了在计算agg节点的输出元组时当前输入组已计算的agg值.*---------------------*//*thesestructsareprivateinnodeAgg.c:*///在nodeAgg.c中私有的结构体typedefstructAggStatePerAggData*AggStatePerAgg;typedefstructAggStatePerTransData*AggStatePerTrans;typedefstructAggStatePerGroupData*AggStatePerGroup;typedefstructAggStatePerPhaseData*AggStatePerPhase;typedefstructAggStatePerHashData*AggStatePerHash;typedefstructAggState{//第一个字段是NodeTag(继承自ScanState)ScanStatess;/*itsfirstfieldisNodeTag*///targetlist和quals中所有的AggrefList*aggs;/*allAggrefnodesintargetlist&quals*///链表的大小(可以为0)intnumaggs;/*lengthoflist(couldbezero!)*///pertrans条目大小intnumtrans;/*numberofpertransitems*///Agg策略模式AggStrategyaggstrategy;/*strategymode*///agg-splitting模式,参见nodes.hAggSplitaggsplit;/*agg-splittingmode,seenodes.h*///指向当前步骤数据的指针AggStatePerPhasephase;/*pointertocurrentphasedata*///步骤数(包括0)intnumphases;/*numberofphases(includingphase0)*///当前步骤intcurrent_phase;/*currentphasenumber*///per-Aggref信息AggStatePerAggperagg;/*per-Aggrefinformation*///per-Trans状态信息AggStatePerTranspertrans;/*per-Transstateinformation*///长生命周期数据的ExprContexts(hashtable)ExprContext*hashcontext;/*econtextsforlong-liveddata(hashtable)*/////长生命周期数据的ExprContexts(每一个GS使用)ExprContext**aggcontexts;/*econtextsforlong-liveddata(perGS)*///输入表达式的ExprContextExprContext*tmpcontext;/*econtextforinputexpressions*/#defineFIELDNO_AGGSTATE_CURAGGCONTEXT14//当前活跃的aggcontextExprContext*curaggcontext;/*currentlyactiveaggcontext*///当前活跃的aggregate(如存在)AggStatePerAggcurperagg;/*currentlyactiveaggregate,ifany*/#defineFIELDNO_AGGSTATE_CURPERTRANS16//当前活跃的transstateAggStatePerTranscurpertrans;/*currentlyactivetransstate,ifany*///输入结束?boolinput_done;/*indicatesendofinput*///Agg扫描结束?boolagg_done;/*indicatescompletionofAggscan*///最后一个groupingsetintprojected_set;/*Thelastprojectedgroupingset*/#defineFIELDNO_AGGSTATE_CURRENT_SET20//将要解析的当前groupingsetintcurrent_set;/*Thecurrentgroupingsetbeingevaluated*///当前投影操作的分组列Bitmapset*grouped_cols;/*groupedcolsincurrentprojection*///倒序的分组列链表List*all_grouped_cols;/*listofallgroupedcolsinDESCorder*//*Thesefieldsareforgroupingsetphasedata*///--------下面的列用于groupingset步骤数据//所有步骤中最大的sets大小intmaxsets;/*Themaxnumberofsetsinanyphase*///所有步骤的数组AggStatePerPhasephases;/*arrayofallphases*///对于phases>1,已排序的输入信息Tuplesortstate*sort_in;/*sortedinputtophases>1*///对于下一个步骤,输入已拷贝Tuplesortstate*sort_out;/*inputiscopiedherefornextphase*///排序结果的slotTupleTableSlot*sort_slot;/*slotforsortresults*//*thesefieldsareusedinAGG_PLAINandAGG_SORTEDmodes:*///-------下面的列用于AGG_PLAIN和AGG_SORTED模式://per-group指针的groupingset编号数组AggStatePerGroup*pergroups;/*groupingsetindexedarrayofper-group*pointers*///当前组的第一个元组拷贝HeapTuplegrp_firstTuple;/*copyoffirsttupleofcurrentgroup*//*thesefieldsareusedinAGG_HASHEDandAGG_MIXEDmodes:*///---------下面的列用于AGG_HASHED和AGG_MIXED模式://是否已填充hash表?booltable_filled;/*hashtablefilledyet?*///hash桶数?intnum_hashes;//相应的哈希表数据数组AggStatePerHashperhash;/*arrayofper-hashtabledata*///per-group指针的groupingset编号数组AggStatePerGroup*hash_pergroup;/*groupingsetindexedarrayof*per-grouppointers*//*supportforevaluationofagginputexpressions:*///----------agg输入表达式解析支持#defineFIELDNO_AGGSTATE_ALL_PERGROUPS34//首先是->pergroups,然后是hash_pergroupAggStatePerGroup*all_pergroups;/*arrayoffirst->pergroups,than*->hash_pergroup*///投影实现机制ProjectionInfo*combinedproj;/*projectionmachinery*/}AggState;/*PrimitiveoptionssupportedbynodeAgg.c:*///nodeag.c支持的基本选项#defineAGGSPLITOP_COMBINE0x01/*substitutecombinefnfortransfn*/#defineAGGSPLITOP_SKIPFINAL0x02/*skipfinalfn,returnstateas-is*/#defineAGGSPLITOP_SERIALIZE0x04/*applyserializefntooutput*/#defineAGGSPLITOP_DESERIALIZE0x08/*applydeserializefntoinput*//*Supportedoperatingmodes(i.e.,usefulcombinationsoftheseoptions):*///支持的操作模式typedefenumAggSplit{/*Basic,non-splitaggregation:*///基本:非split聚合AGGSPLIT_SIMPLE=0,/*Initialphaseofpartialaggregation,withserialization:*///部分聚合的初始步骤,序列化AGGSPLIT_INITIAL_SERIAL=AGGSPLITOP_SKIPFINAL|AGGSPLITOP_SERIALIZE,/*Finalphaseofpartialaggregation,withdeserialization:*///部分聚合的最终步骤,反序列化AGGSPLIT_FINAL_DESERIAL=AGGSPLITOP_COMBINE|AGGSPLITOP_DESERIALIZE}AggSplit;/*TestwhetheranAggSplitvalueselectseachprimitiveoption:*///测试AggSplit选择了哪些基本选项#defineDO_AGGSPLIT_COMBINE(as)(((as)&AGGSPLITOP_COMBINE)!=0)#defineDO_AGGSPLIT_SKIPFINAL(as)(((as)&AGGSPLITOP_SKIPFINAL)!=0)#defineDO_AGGSPLIT_SERIALIZE(as)(((as)&AGGSPLITOP_SERIALIZE)!=0)#defineDO_AGGSPLIT_DESERIALIZE(as)(((as)&AGGSPLITOP_DESERIALIZE)!=0)

AggStatePerAggData
per-aggregate信息,这个结构体包含了调用最终函数的信息,用以从状态值中产生一个最终的聚合结果.如果查询中有多个相同的Aggrefs,共享相同的per-agg数据.

/**AggStatePerAggData-per-aggregateinformation*AggStatePerAggData-per-aggregate信息**Thiscontainstheinformationneededtocallthefinalfunction,toproduce*afinalaggregateresultfromthestatevalue.Iftherearemultiple*identicalAggrefsinthequery,theycanallsharethesameper-aggdata.*这个结构体包含了调用最终函数的信息,用以从状态值中产生一个最终的聚合结果.*如果查询中有多个相同的Aggrefs,共享相同的per-agg数据.**ThesevaluesaresetupduringExecInitAgg()anddonotchangethereafter.*这些值在ExecInitAgg()中设置,此后不再变化.*/typedefstructAggStatePerAggData{/**LinktoanAggrefexprthisstatevalueisfor.*链接到该状态值代表的Aggrefexpr上.**TherecanbemultipleidenticalAggref'ssharingthesameper-agg.This*pointstothefirstoneofthem.*可能有多个相同的Aggref共享相同的per-agg.指向第一个.*/Aggref*aggref;/*indextothestatevaluewhichthisaggshoulduse*///该agg应使用的状态值索引inttransno;/*OptionalOidoffinalfunction(maybeInvalidOid)*///finalfunction函数的Oid(可以是InvalidOid)Oidfinalfn_oid;/**fmgrlookupdataforfinalfunction---onlyvalidwhenfinalfn_oidis*notInvalidOid.*finalfunction的fmgr检索数据---在finalfn_oid不是InvalidOid时才有效*/FmgrInfofinalfn;/**Numberofargumentstopasstothefinalfn.Thisisalwaysatleast1*(thetransitionstatevalue)plusanyordered-setdirectargs.Ifthe*finalfnwantsextraargsthenwepassnullscorrespondingtothe*aggregatedinputcolumns.*传递给finalfn的参数个数.*这通常不小于1(转换状态值)加上所有已排序集合的直接参数.*如果finalfn需要特别的参数,那么会传递nulls对应聚合的输入列.**/intnumFinalArgs;/*ExprStatesforanydirect-argumentexpressions*///所有直接参数表达式的ExprStatesList*aggdirectargs;/**Weneedthelenandbyvalinfofortheagg'sresultdatatypeinorder*toknowhowtocopy/deletevalues.*对于agg结果数据类型需要长度和byval信息,用以知道如何拷贝和删除值.*/int16resulttypeLen;boolresulttypeByVal;/**"shareable"isfalseifthisaggcannotsharestatevalueswithother*aggregatesbecausethefinalfunctionisread-write.*如因为finalfunction是RW,agg不能与其他aggregates共享状态值,则shareable为F*/boolshareable;}AggStatePerAggData;

AggStatePerTransData
聚合状态值信息(per aggregate state value information), 通过输入行调用转换函数更新聚合状态值的工作状态.该结构体不会存储从转换状态而来的用于产生最终聚合结果的相关信息,这些信息会存储在AggStatePerAggData中.

/**AggStatePerTransData-peraggregatestatevalueinformation*AggStatePerTransData-聚合状态值信息**Workingstateforupdatingtheaggregate'sstatevalue,bycallingthe*transitionfunctionwithaninputrow.Thisstructdoesnotstorethe*informationneededtoproducethefinalaggregateresultfromthetransition*state,that'sstoredinAggStatePerAggDatainstead.Thisseparationallows*multipleaggregateresultstobeproducedfromasinglestatevalue.*通过输入行调用转换函数更新聚合状态值的工作状态.*该结构体不会存储从转换状态而来的用于产生最终聚合结果的相关信息,这些信息会存储在AggStatePerAggData中.*这样的分离可以做到多个聚合结果可通过单个状态值产生.*/typedefstructAggStatePerTransData{/**ThesevaluesaresetupduringExecInitAgg()anddonotchange*thereafter:*这些值在ExecInitAgg()执行期间设置,以后不会修改.*//**LinktoanAggrefexprthisstatevalueisfor.*链接到该状态值所代表的Aggref表达式上面.**TherecanbemultipleAggref'ssharingthesamestatevalue,solongas*theinputsandtransitionfunctionsareidenticalandthefinal*functionsarenotread-write.Thispointstothefirstoneofthem.*参见AggStatePerAggData结构体注释*/Aggref*aggref;/**IsthisstatevalueactuallybeingsharedbymorethanoneAggref?*是否共享?*/boolaggshared;/**Numberofaggregatedinputcolumns.ThisincludesORDERBYexpressions*inboththeplain-aggandordered-setcases.Ordered-setdirectargs*arenotcounted,though.*聚合输入列个数.*/intnumInputs;/**Numberofaggregatedinputcolumnstopasstothetransfn.This*includestheORDERBYcolumnsforordered-setaggs,butnotforplain*aggs.(Thisdoesn'tcountthetransitionstatevalue!)*传递给transfn的聚合输入列个数.*/intnumTransInputs;/*Oidofthestatetransitionorcombinefunction*///转换或组合函数OidOidtransfn_oid;/*OidoftheserializationfunctionorInvalidOid*///序列化函数Oid或InvalidOidOidserialfn_oid;/*OidofthedeserializationfunctionorInvalidOid*///反序列化函数Oid或InvalidOidOiddeserialfn_oid;/*Oidofstatevalue'sdatatype*///状态值数据类型OidOidaggtranstype;/**fmgrlookupdatafortransitionfunctionorcombinefunction.Notein*particularthatthefn_strictflagiskepthere.*转换函数或组合函数的fmgr检索数据.*/FmgrInfotransfn;/*fmgrlookupdataforserializationfunction*///序列化函数fmgrFmgrInfoserialfn;/*fmgrlookupdatafordeserializationfunction*///反序列化函数fmgrFmgrInfodeserialfn;/*Inputcollationderivedforaggregate*///派生于聚合的输入排序规则OidaggCollation;/*numberofsortingcolumns*///排序列个数intnumSortCols;/*numberofsortingcolumnstoconsiderinDISTINCTcomparisons*//*(thisiseitherzeroorthesameasnumSortCols)*///在DISTINCT比较时需考虑的排序列数intnumDistinctCols;/*deconstructedsortinginformation(arraysoflengthnumSortCols)*///重组排序信息AttrNumber*sortColIdx;Oid*sortOperators;Oid*sortCollations;bool*sortNullsFirst;/**Comparatorsforinputcolumns---onlyset/usedwhenaggregatehas*DISTINCTflag.equalfnOneversionisusedforsingle-column*comparisons,equalfnMultiforthecaseofmultiplecolumns.*输入列比较器,在聚合有DISTINCT标记时才会设置/使用*equalfnOne用于单个列比较,equalfnMulti用于多列.*/FmgrInfoequalfnOne;ExprState*equalfnMulti;/**initialvaluefrompg_aggregateentry*pg_aggregate条目的初始值*/DatuminitValue;boolinitValueIsNull;/**Weneedthelenandbyvalinfofortheagg'sinputandtransitiondata*typesinordertoknowhowtocopy/deletevalues.*需要聚合输入的len和byval信息以及转换数据类型,以便知道如何拷贝/删除值**Notethattheinfofortheinputtypeisusedonlywhenhandling*DISTINCTaggswithjustoneargument,sothereisonlyoneinputtype.*注意:输入类型的信息仅用于处理单个参数的DISTINCT聚合,因此只有一个输入类型*/int16inputtypeLen,transtypeLen;boolinputtypeByVal,transtypeByVal;/**Slotsforholdingtheevaluatedinputarguments.Thesearesetup*duringExecInitAgg()andthenusedforeachinputrowrequiringeither*FILTERorORDERBY/DISTINCTprocessing.*保存解析输入参数的slots.*在ExecInitAgg()中设置用于每个输入行,在FILTER或ORDERBY/DISTINCT处理过程中需要.*///当前输入的tupleTupleTableSlot*sortslot;/*currentinputtuple*///用于多列DISTINCTTupleTableSlot*uniqslot;/*usedformulti-columnDISTINCT*///输入元组描述符TupleDescsortdesc;/*descriptorofinputtuples*//**Thesevaluesareworkingstatethatisinitializedatthestartofan*inputtuplegroupandupdatedforeachinputtuple.*这些值是在输入tuplegroup被初始化时的工作状态,在处理每个tuple都会更新.**Forasimple(nonDISTINCT/ORDERBY)aggregate,wejustfeedtheinput*valuesstraighttothetransitionfunction.Ifit'sDISTINCTor*requiresORDERBY,wepasstheinputvaluesintoaTuplesortobject;*thenatcompletionoftheinputtuplegroup,wescanthesortedvalues,*eliminateduplicatesifneeded,andrunthetransitionfunctiononthe*rest.*对于简单的(不是DISTINCT/ORDERBY)聚合,直接把输入值提供给转换函数即可.*如果是DISTINCT/ORDERBY,传递输入值给Tuplesort对象,*在输入的tuple组结束时,扫描已存储值,如需要去重并在剩余的元组上执行转换函数**Weneedaseparatetuplesortforeachgroupingset.*需要为每一个groupingset提供tuplesort*///排序对象,仅用于DISTINCT/ORDERBYTuplesortstate**sortstates;/*sortobjects,ifDISTINCTorORDERBY*//**Thisfieldisapre-initializedFunctionCallInfostructusedfor*callingthisaggregate'stransfn.Wesaveafewcyclesperrowbynot*re-initializingtheunchangingfields;whichisn'tmuch,butitseems*worththeextraspaceconsumption.*该字段是预初始化FunctionCallInfo结构体,用于调用聚合的转换函数transfn.*对于每一行,通过减少不会改变的字段的初始化可以节省一些CPU处理周期,*但这个收益不会太大,但看起来值得额外的空间消耗.*/FunctionCallInfoDatatransfn_fcinfo;/*Likewiseforserializationanddeserializationfunctions*///序列化和反序列化函数信息FunctionCallInfoDataserialfn_fcinfo;FunctionCallInfoDatadeserialfn_fcinfo;}AggStatePerTransData;

AggStatePerGroupData
per-aggregate-per-group工作状态,这些工作状态值在第一个输入tuple group时初始化,后续在处理每个输入tuple时更新.

/**AggStatePerGroupData-per-aggregate-per-groupworkingstate*AggStatePerGroupData-per-aggregate-per-group工作状态**Thesevaluesareworkingstatethatisinitializedatthestartof*aninputtuplegroupandupdatedforeachinputtuple.*这些工作状态值在第一个输入tuplegroup时初始化,后续在处理每个输入tuple时更新.**InAGG_PLAINandAGG_SORTEDmodes,wehaveasinglearrayofthese*structs(pointedtobyaggstate->pergroup);were-usethearrayfor*eachinputgroup,ifit'sAGG_SORTEDmode.InAGG_HASHEDmode,the*hashtablecontainsanarrayofthesestructsforeachtuplegroup.*在AGG_PLAIN/AGG_SORTED模式,这些结构体都有一个单独的数组(aggstate->pergroup指向这些结构体);*在AGG_SORTED模式,对于每一个输入group,都会重用这些数组.*在AGG_HASHED模式,hash表中都有对应每一个tuplegroup的这些结构体的数组.**Logically,thesortstatefieldbelongsinthisstruct,butwedonot*keepithereforspacereasons:wedon'tsupportDISTINCTaggregates*inAGG_HASHEDmode,sothere'snoreasontouseupapointerfield*ineveryentryofthehashtable.*逻辑上来说,sortstate字段属于该结构体,但出于空间大小考虑,不在这里保存:*在AGG_HASHED模式,不支持DISTINCT聚合,因此没有理由在hash表的每一个条目中都包含指针域.*/typedefstructAggStatePerGroupData{#defineFIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE0//当前转换值DatumtransValue;/*currenttransitionvalue*/#defineFIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL1booltransValueIsNull;#defineFIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE2//如transValue尚未设置,则为TboolnoTransValue;/*trueiftransValuenotsetyet*//**Note:noTransValueinitiallyhasthesamevalueastransValueIsNull,*andiftruebothareclearedtofalseatthesametime.Theyarenot*thesamethough:iftransfnlaterreturnsaNULL,wewanttokeepthat*NULLandnotauto-replaceitwithalaterinputvalue.Onlythefirst*non-NULLinputwillbeauto-substituted.*注意:noTransValue与transValueIsNull在初始化时值一样,如同为T,则同时将二者设置为F.*但它们并不相同,如果transfn后续返回NULL,需要保存该NULL值而不是用随后的输入值自动替换之.*只有在第一个非NULL输入会被自动替换.*/}AggStatePerGroupData;

AggStatePerPhaseData
per-grouping-set-phase状态.Grouping sets会被分拆为多个”步骤”,每一个单独的步骤在输入上都会完成一轮处理.

/**AggStatePerPhaseData-per-grouping-set-phasestate*AggStatePerPhaseData-per-grouping-set-phase状态**Groupingsetsaredividedinto"phases",whereasinglephasecanbe*processedinonepassovertheinput.Ifthereismorethanonephase,then*attheendofinputfromthecurrentphase,stateisresetandanotherpass*takenoverthedatawhichhasbeenre-sortedinthemeantime.*Groupingsets会被分拆为多个"步骤",每一个单独的步骤在输入上都会完成一轮处理.*如果步骤多于一个,在当前步骤的最后一个输入处,状态会被重置,同时另一次传递接管了在此期间重排的数据.**Accordingly,eachphasespecifiesalistofgroupingsetsandgroupclause*information,pluseachphaseafterthefirstalsohasasortorder.*相应的,每一个步骤指定了groupingsets和groupclause信息链表,外加在第一个步骤的排序.*/typedefstructAggStatePerPhaseData{//该步骤使用的策略AggStrategyaggstrategy;/*strategyforthisphase*///groupingsets个数,如无则为0intnumsets;/*numberofgroupingsets(or0)*///groupingsets的大小int*gset_lengths;/*lengthsofgroupingsets*///rollup(上卷)列组Bitmapset**grouped_cols;/*columngroupingsforrollup*///返回等价的表达式,比较列序号作为索引ExprState**eqfunctions;/*expressionreturningequality,indexedby*nrofcolstocompare*///对应步骤数据的Agg节点Agg*aggnode;/*Aggnodeforphasedata*///该步骤的输入排序Sort节点Sort*sortnode;/*Sortnodeforinputorderingforphase*///转换函数解析ExprState*evaltrans;/*evaluationoftransitionfunctions*/}AggStatePerPhaseData;

AggStatePerHashData
per-hashtable状态.使用哈希进行grouping set,每一个grouping set都会有一个这样的结构体.

/**AggStatePerHashData-per-hashtablestate*AggStatePerHashData-per-hashtable状态**Whendoinggroupingsetswithhashing,wehaveoneoftheseforeach*groupingset.(Whendoinghashingwithoutgroupingsets,wehavejustoneof*them.)*使用哈希进行groupingset,每一个groupingset都会有一个这样的结构体.*(如无groupingsets执行哈希,则只需要一个即可)*/typedefstructAggStatePerHashData{//每一个group都有一个条目的哈希表TupleHashTablehashtable;/*hashtablewithoneentrypergroup*///访问哈希表的迭代器TupleHashIteratorhashiter;/*foriteratingthroughhashtable*///装载哈希表的slotTupleTableSlot*hashslot;/*slotforloadinghashtable*///per-grouping-field哈希函数FmgrInfo*hashfunctions;/*per-grouping-fieldhashfns*///per-grouping-field等价函数Oid*eqfuncoids;/*per-grouping-fieldequalityfns*///哈希键列个数intnumCols;/*numberofhashkeycolumns*///哈希表中的列数intnumhashGrpCols;/*numberofcolumnsinhashtable*///请求哈希最大的列intlargestGrpColIdx;/*largestcolrequiredforhashing*///输入slot中的hashcol索引数组AttrNumber*hashGrpColIdxInput;/*hashcolindicesininputslot*///hashtbl元组索引数组AttrNumber*hashGrpColIdxHash;/*indicesinhashtbltuples*///元素的Agg节点,用于numGroups等等Agg*aggnode;/*originalAggnode,fornumGroupsetc.*/}AggStatePerHashData;

感谢各位的阅读,以上就是“PostgreSQL执行聚合函数所使用的数据结构有哪些”的内容了,经过本文的学习后,相信大家对PostgreSQL执行聚合函数所使用的数据结构有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!