数据库性能优化是一个非常重要而复杂的工作,它可以大大提高数据库的查询效率和响应速度,从而提高整个系统的性能和稳定性。在这个过程中,需要不断地进行优化,不断地寻找和解决数据库性能瓶颈,才能取得最好的效果。这需要我们孜孜不倦地投入精力和时间,不断地学习和探索新的优化方法和技巧,为整个系统的高效运行保驾护航。
本文主要介绍一种openGemini采用的查询计划模板优化方法, 通过对比测试,优化后性能可提升40%。
什么是查询计划模板优化?
在openGemini内部,查询引擎执行查询时,一般流程是通过查询优化器等一系列步骤生成对应的查询计划,再按查询计划执行,返回结果数据。但在实际应用中我们发现,尤其在运维监控场景,大量查询语句是在重复执行(仅时间范围有变化),并通过抓取火焰图发现,每次查询过程,查询逻辑计划生成的耗时占比偏大,有很大的优化空间。正好适用于查询计划模板优化方法。
优化方法
通过对大量应用场景的深入分析和了解,提取了大量高频查询语句,抽象后分类如下:
序号 | |
| 1 | Select [AGG] From [MST] Where [CON] Group by [time] |
| 2 | Select [AGG] From [MST] Where [CON] Group by [time],[tags] |
| 3 | Select [AGG] From [MST] Where [CON] Group by [time] Limit |
| 4 | Select [Field] From [MST] Where [CON] |
| 5 | Select [AGG] From [MST] Group by [tags] |
查询语句对应参数化格式 | 模板类型 | |
Select [AGG] From [MST] Where [CON] Group by [time] | 1 | |
Select [AGG] From [MST] Where [CON] Group by [time],[tags] | 1 | |
Select [AGG] From [MST] Where [CON] Group by [time] Limit | 2 | |
| 4. | Select [Field] From [MST] Where [CON] | 3 |
Select [AGG] From [MST] Group by [tags] | 4 |
类型 | 模板名称 | 计划结构 |
1 | AGG_INTERVAL | LogicalHttpSender->LogicalFill->LogicalProject->LogicalInterval-> LogicalAggregate->LogicalExchange->LogicalAggregate-> LogicalExchange->LogicalIndexScan->LogicalAggregate-> LogicalExchange->LogicalAggregate->LogicalReader-> LogicalExchange-> LogicalAggregate-> LogicalAggregate-> LogicalSeries |
2 | AGG_INTERVAL_LIMIT | LogicalHttpSender->LogicalLimit->LogicalFill->LogicalProject-> LogicalInterval->LogicalAggregate->LogicalExchange-> LogicalAggregate->LogicalExchange->LogicalIndexScan-> LogicalAggregate->LogicalExchange->LogicalAggregate-> LogicalReader->LogicalExchange->LogicalAggregate-> LogicalAggregate->LogicalSeries |
3 | NO_AGG_NO_GROUP | LogicalHttpSender->LogicalProject->LogicalExchange-> LogicalExchange->LogicalIndexScan->LogicalExchange-> LogicalReader->LogicalExchange->LogicalSeries |
4 | AGG_GROUP | LogicalHttpSender->LogicalProject->LogicalAggregate-> LogicalExchange->LogicalAggregate->LogicalExchange-> LogicalIndexScan->LogicalAggregate->LogicalExchange-> LogicalReader |
计划模板的代码集中在openGemini的engine/executor/plan_type.go和engine/executor/plan_type_shard.go文件中,有兴趣的读者可以进行阅读,本文后续基于优化后的版本在相同数据和查询模型下进行对比测试,优化前后QPS对比下图所示,可以看到总体提升在40%左右。
//如下这部分内容排版时作为引用
数据点总量为1440000,时间线数量为1000,数据生成的时间点间隔为60s,查询总数为10000一次。
继续抓取优化后的火焰图与优化前做对比,下图左侧是优化后的火焰图,右侧是优化前的,可以看到逻辑计划生成部分占比明显减少。
优化后逻辑计划生成部分的火焰图如下图所示,可以看到优化器部分的开销全部消失。
如何添加新模板
- 向plan_type_shard.go中的TemplateSql中添加新查询模板的一个范例查询并在plan_type.go的init()中将这个新查询模板的枚举名称加入PlanTypes的初始化中,在系统启动时会对TemplateSql中所有查询进行遍历生成每个查询对应的逻辑计划并将其作为模板计划放入plan_type.go中的SqlplanTemplate和StorePlanTemplate中,它们通过下标保证对应关系。
- 向plan_type.go中添加新查询模板的匹配函数,如NO_AGG_NO_GROUP模板的匹配函数如下图所示,根据匹配函数判断输入的查询schema属于哪种模板类型。
- 将新查询模板对应的匹配函数加入plan_type.go的init()函数中初始化MatchPlanFunc,在查询模板匹配流程中会对MatchPlanFunc中所有匹配函数进行调用,找到查询符合的模板类型,然后根据模板类型找到步骤1中SqlplanTemplate/StorePlanTemplate对应下标的模板计划,最后使用模板计划通过调用NewPlanBySchemaAndSrcPlan()来从模板计划生成该查询对应的实际逻辑计划。
总结
数据库性能优化是一个需要耐心和毅力的过程。需要不断地进行分析和优化,找出潜在的性能问题,并采取相应的措施进行优化。只有经过不断的努力和实践,才能真正提高数据库系统的性能,为业务提供更好的支持。
本文介绍了如何基于火焰图分析优化openGemini的一个案例,同时也介绍了如何新增一个查询模板,希望对读者有所帮助。
openGemini官网:http://www.openGemini.org
openGemini开源地址:https://github.com/openGemini
openGemini公众号:

欢迎关注~ 诚邀你加入 openGemini 社区,共建、共治、共享未来!




