批量查询优化的背景
♦ 什么是批量查询?
批量查询是将多条查询语句打包,一次发给数据库,数据库内部逐条执行,将结果汇总后返回客户端,我们称之为批量查询。
♦ 批量查询场景
在运维监控场景中,监控面板存在非常多的图表(上图仅仅是其中一部分),这些图表会定期查询更新数据,一部分图表可能由上百个查询结果绘制而成,如果所有图表中的查询全部独立发送到时序数据库,这将导致并发激增,客户端和数据库都无法支撑,因此只能把查询语句打包给到时序数据库,由数据库批量执行并返回结果数据。
使用批量查询时,查询语句之间需要用分号“;”进行分割,如下
SELECT disk_usage FROM table; SELECT disk_io FROM table;…
♦ 批量查询引发的问题
当批量查询到来时,openGemini通常是依次执行每条查询语句,执行完成后再执行下一条,因此无法利用openGemini的并发能力。当批量查询语句很多时,往往查询周期较长,无法满足性能诉求,因此产生了优化的需求。
优化方法
openGemini的内核由Golang实现,其GMP模型高度支持并发性,非常适合将串行改为并行。
-
Golang GMP模型
KSE是Kernel Scheduling Entity的缩写,其是可被操作系统内核调度器调度的对象实体,是操作系统内核的最小调度单元,可以简单理解为内核级线程。
G-M-P分别代表:
G - Goroutine,Go协程,是参与调度与执行的最小单位
M - Machine,指的是系统级线程,由系统调用产生
P - Processor,指的是逻辑处理器,P关联了的本地可运行G的队列,最多可存放256个G。
因此针对串行查询的性能问题,可以利用Golang的GMP模型的优势,进行并行化改造。
-
openGemini自适应并行查询任务调度器
openGemini自适应并行查询任务调度器将根据机器规格,创建相应数量的goroutine用于并行执行查询命令,例如对于4U的机器,并发度为4(效率最高),如果12条批量查询语句,每次并发执行4条查询语句,仅需要3轮就可以执行完成,而在没有加入自适应并行查询任务调度器之前,12条查询语句要执行12次,无法充分利用CPU的并发能力。
相关源码文件:open_src/Influx/query/executor.go
具体方法:
func executeParallelQuery()
优化后性能参考
测试规格:(12节点集群,单节点规格32U128G)
openGemini采用该优化的版本为 v1.1.0,可在配置文件中打开该功能开关即可。
//如下是代码块
[http]
parallel-query-in-batch-enabled = true
总结
本文介绍了什么是批量查询,以及批量查询串行执行带来性能问题,openGemini充分利用了Go语言强大的并发处理能力,对串行查询进行并发改造,提出的自适应并行查询任务调度器,以解决串行查询的性能问题。希望本文对大家了解openGemini有所帮助。
openGemini官网:www.openGemini.org
openGemini开源地址:github.com/openGemini
openGemini公众号:
欢迎关注~ 诚邀你加入 openGemini 社区,共建、共治、共享未来!