openGauss源码解析(140)
openGauss源码解析:执行器解析(33)
7.5.2 VecHashAggCodeGen类
对于hash聚合来说,数据库会根据“GROUP BY”字段后面的值算出哈希值,并根据前面使用的聚合函数在内存中维护对应的列表。VecHashAggCodeGen类的接口实现在“codegen/vechashaggcodegen.h”文件中,接口的说明如表7-34所示。
表7-34 VecHashAggCodeGen接口汇总
接口名称 | 接口类型 | 职责描述 |
GetAlignedScale | API | 计算当前表达式scale |
AggRefJittable | API | 判断表达式是否支持LLVM化 |
AggRefFastJittable | API | 判断当前表达式是否能用快速CodeGen |
AgghashingJittable | API | 判断Agg节点是否能LLVM化 |
HashAggCodeGen | API | HashAgg节点构建IR函数的主函数 |
SonicHashAggCodeGen | API | Sonic hashagg节点构建IR函数的主函数 |
HashBatchCodeGen | API | 为“hashBatch”函数生成LLVM函数指针 |
MatchOneKeyCodeGen | API | 为“match_key”函数生成LLVM函数指针 |
BatchAggJittable | API | 判断当前batch aggregation节点是否支持LLVM化 |
BatchAggregationCodeGen | API | 为BatchAggregation节点生成LLVM函数指针 |
SonicBatchAggregationCodeGen | API | 为SonicBatchAggregation节点生成LLVM函数指针 |
openGauss内核在处理Agg节点时,首先在ExecInitVecAggregation函数中判断是否进行CodeGen,如果行数大于codegen_cost_threshold参数那么可以进行CodeGen。
bool consider_codegen =
CodeGenThreadObjectReady() &&CodeGenPassThreshold(((Plan*)outer_plan)->plan_rows,
estate->es_plannedstmt->num_nodes, ((Plan*)outer_plan)->dop);
if (consider_codegen) {
if (node->aggstrategy == AGG_HASHED && node->is_sonichash) {
dorado::VecHashAggCodeGen::SonicHashAggCodeGen(aggstate);
} else if (node->aggstrategy == AGG_HASHED) {
dorado::VecHashAggCodeGen::HashAggCodeGen(aggstate);
}
}
如果输出行数小于codegen_cost_threshold,那么codegen的成本要大于执行优化的成本。如果节点是sonic类型,执行SonicHashAggCodeGen函数;一般的HashAgg节点执行HashAggCodeGen函数。SonicHashAggCodeGen函数和HashAggCodeGen函数的执行流程如图7-26所示。
图7-26 HashAgg节点CodeGen流程
HashAggCodeGen函数是HashAgg节点LLVM化的主入口。openGauss在结构体VecAggState中定义哈希策略的Agg节点。openGauss针对LLVM化Agg节点增加了5个参数用来保存codegen后的函数指针:jitted_hashing、jitted_sglhashing、jitted_batchagg、jitted_sonicbatchagg以及jitted_SortAggMatchKey。而且openGauss在addFunctionToMCJit函数中用生成的IR函数与节点对应的函数指针构造一个链表。