这篇文章主要讲解了“PostgreSQL执行聚合函数所使用的数据结构有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL执行聚合函数所使用的数据结构有哪些”吧!
一、数据结构
AggState
聚合函数执行时状态结构体,内含AggStatePerAgg等结构体
//在nodeAgg.c中私有的结构体
typedef struct AggStatePerAggData *AggStatePerAgg;
typedef struct AggStatePerTransData *AggStatePerTrans;
typedef struct AggStatePerGroupData *AggStatePerGroup;
typedef struct AggStatePerPhaseData *AggStatePerPhase;
typedef struct AggStatePerHashData *AggStatePerHash;
typedef struct AggState
{
//第一个字段是NodeTag(继承自ScanState)
ScanState ss;
//targetlist和quals中所有的Aggref
List *aggs;
//链表的大小(可以为0)
int numaggs;
//pertrans条目大小
int numtrans;
//Agg策略模式
AggStrategy aggstrategy;
//agg-splitting模式,参见nodes.h
AggSplit aggsplit;
//指向当前步骤数据的指针
AggStatePerPhase phase;
//步骤数(包括0)
int numphases;
//当前步骤
int current_phase;
//per-Aggref信息
AggStatePerAgg peragg;
//per-Trans状态信息
AggStatePerTrans pertrans;
//长生命周期数据的ExprContexts(hashtable)
ExprContext *hashcontext;
////长生命周期数据的ExprContexts(每一个GS使用)
ExprContext **aggcontexts;
//输入表达式的ExprContext
ExprContext *tmpcontext;
#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
//当前活跃的aggcontext
ExprContext *curaggcontext;
//当前活跃的aggregate(如存在)
AggStatePerAgg curperagg;
#define FIELDNO_AGGSTATE_CURPERTRANS 16
//当前活跃的trans state
AggStatePerTrans curpertrans;
//输入结束?
bool input_done;
//Agg扫描结束?
bool agg_done;
//最后一个grouping set
int projected_set;
#define FIELDNO_AGGSTATE_CURRENT_SET 20
//将要解析的当前grouping set
int current_set;
//当前投影操作的分组列
Bitmapset *grouped_cols;
//倒序的分组列链表
List *all_grouped_cols;
//-------- 下面的列用于grouping set步骤数据
//所有步骤中最大的sets大小
int maxsets;
//所有步骤的数组
AggStatePerPhase phases;
//对于phases > 1,已排序的输入信息
Tuplesortstate *sort_in;
//对于下一个步骤,输入已拷贝
Tuplesortstate *sort_out;
//排序结果的slot
TupleTableSlot *sort_slot;
//------- 下面的列用于AGG_PLAIN和AGG_SORTED模式:
//per-group指针的grouping set编号数组
AggStatePerGroup *pergroups;
//当前组的第一个元组拷贝
HeapTuple grp_firstTuple;
//--------- 下面的列用于AGG_HASHED和AGG_MIXED模式:
//是否已填充hash表?
bool table_filled;
//hash桶数?
int num_hashes;
//相应的哈希表数据数组
AggStatePerHash perhash;
//per-group指针的grouping set编号数组
AggStatePerGroup *hash_pergroup;
//---------- agg输入表达式解析支持
#define FIELDNO_AGGSTATE_ALL_PERGROUPS 34
//首先是->pergroups,然后是hash_pergroup
AggStatePerGroup *all_pergroups;
//投影实现机制
ProjectionInfo *combinedproj;
} AggState;
//nodeag .c支持的基本选项
#define AGGSPLITOP_COMBINE 0x01
#define AGGSPLITOP_SKIPFINAL 0x02
#define AGGSPLITOP_SERIALIZE 0x04
#define AGGSPLITOP_DESERIALIZE 0x08
//支持的操作模式
typedef enum AggSplit
{
//基本 : 非split聚合
AGGSPLIT_SIMPLE = 0,
//部分聚合的初始步骤,序列化
AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
//部分聚合的最终步骤,反序列化
AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
} AggSplit;
//测试AggSplit选择了哪些基本选项
#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)
AggStatePerAggData
per-aggregate信息,这个结构体包含了调用最终函数的信息,用以从状态值中产生一个最终的聚合结果.如果查询中有多个相同的Aggrefs,共享相同的per-agg数据.
typedef struct AggStatePerAggData
{
Aggref *aggref;
//该agg应使用的状态值索引
int transno;
//final function函数的Oid(可以是InvalidOid)
Oid finalfn_oid;
FmgrInfo finalfn;
int numFinalArgs;
//所有直接参数表达式的ExprStates
List *aggdirectargs;
int16 resulttypeLen;
bool resulttypeByVal;
bool shareable;
} AggStatePerAggData;
AggStatePerTransData
聚合状态值信息(per aggregate state value information), 通过输入行调用转换函数更新聚合状态值的工作状态.该结构体不会存储从转换状态而来的用于产生最终聚合结果的相关信息,这些信息会存储在AggStatePerAggData中.
typedef struct AggStatePerTransData
{
Aggref *aggref;
bool aggshared;
int numInputs;
int numTransInputs;
//转换或组合函数Oid
Oid transfn_oid;
//序列化函数Oid或InvalidOid
Oid serialfn_oid;
//反序列化函数Oid或InvalidOid
Oid deserialfn_oid;
//状态值数据类型Oid
Oid aggtranstype;
FmgrInfo transfn;
//序列化函数fmgr
FmgrInfo serialfn;
//反序列化函数fmgr
FmgrInfo deserialfn;
//派生于聚合的输入排序规则
Oid aggCollation;
//排序列个数
int numSortCols;
//在DISTINCT比较时需考虑的排序列数
int numDistinctCols;
//重组排序信息
AttrNumber *sortColIdx;
Oid *sortOperators;
Oid *sortCollations;
bool *sortNullsFirst;
FmgrInfo equalfnOne;
ExprState *equalfnMulti;
Datum initValue;
bool initValueIsNull;
int16 inputtypeLen,
transtypeLen;
bool inputtypeByVal,
transtypeByVal;
//当前输入的tuple
TupleTableSlot *sortslot;
//用于多列DISTINCT
TupleTableSlot *uniqslot;
//输入元组描述符
TupleDesc sortdesc;
//排序对象,仅用于DISTINCT/ORDER BY
Tuplesortstate **sortstates;
FunctionCallInfoData transfn_fcinfo;
//序列化和反序列化函数信息
FunctionCallInfoData serialfn_fcinfo;
FunctionCallInfoData deserialfn_fcinfo;
} AggStatePerTransData;
AggStatePerGroupData
per-aggregate-per-group工作状态,这些工作状态值在第一个输入tuple group时初始化,后续在处理每个输入tuple时更新.
typedef struct AggStatePerGroupData
{
#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE 0
//当前转换值
Datum transValue;
#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL 1
bool transValueIsNull;
#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE 2
//如transValue尚未设置,则为T
bool noTransValue;
} AggStatePerGroupData;
AggStatePerPhaseData
per-grouping-set-phase状态.Grouping sets会被分拆为多个”步骤”,每一个单独的步骤在输入上都会完成一轮处理.
typedef struct AggStatePerPhaseData
{
//该步骤使用的策略
AggStrategy aggstrategy;
//grouping sets个数,如无则为0
int numsets;
//grouping sets的大小
int *gset_lengths;
//rollup(上卷)列组
Bitmapset **grouped_cols;
//返回等价的表达式,比较列序号作为索引
ExprState **eqfunctions;
//对应步骤数据的Agg节点
Agg *aggnode;
//该步骤的输入排序Sort节点
Sort *sortnode;
//转换函数解析
ExprState *evaltrans;
} AggStatePerPhaseData;
AggStatePerHashData
per-hashtable状态.使用哈希进行grouping set,每一个grouping set都会有一个这样的结构体.
typedef struct AggStatePerHashData
{
//每一个group都有一个条目的哈希表
TupleHashTable hashtable;
//访问哈希表的迭代器
TupleHashIterator hashiter;
//装载哈希表的slot
TupleTableSlot *hashslot;
//per-grouping-field哈希函数
FmgrInfo *hashfunctions;
//per-grouping-field等价函数
Oid *eqfuncoids;
//哈希键列个数
int numCols;
//哈希表中的列数
int numhashGrpCols;
//请求哈希最大的列
int largestGrpColIdx;
//输入slot中的hash col索引数组
AttrNumber *hashGrpColIdxInput;
//hashtbl元组索引数组
AttrNumber *hashGrpColIdxHash;
//元素的Agg节点,用于numGroups等等
Agg *aggnode;
} AggStatePerHashData;
感谢各位的阅读,以上就是“PostgreSQL执行聚合函数所使用的数据结构有哪些”的内容了,经过本文的学习后,相信大家对PostgreSQL执行聚合函数所使用的数据结构有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!