openGemini:批量查询优化

原创
2023/11/24 17:08
阅读数 25

批量查询优化的背景

♦ 什么是批量查询?

批量查询是将多条查询语句打包,一次发给数据库,数据库内部逐条执行,将结果汇总后返回客户端,我们称之为批量查询。

♦ 批量查询场景

在运维监控场景中,监控面板存在非常多的图表(上图仅仅是其中一部分),这些图表会定期查询更新数据,一部分图表可能由上百个查询结果绘制而成,如果所有图表中的查询全部独立发送到时序数据库,这将导致并发激增,客户端和数据库都无法支撑,因此只能把查询语句打包给到时序数据库,由数据库批量执行并返回结果数据。

使用批量查询时,查询语句之间需要用分号“;”进行分割,如下

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

查询场景

并发量

平均时延(ms)

批量查询1小时范围50条时间线,1min粒度平均值聚合,背景压力2650万时间线

100

48

200

53

300

64

500

100

批量查询30分钟范围内100条时间线,按1min粒度平均值聚合;背景压力2650万时间线

100

59

200

66

400

108

openGemini采用该优化的版本为 v1.1.0,可在配置文件中打开该功能开关即可。

//如下是代码块

[http]parallel-query-in-batch-enabled = true

总结

本文介绍了什么是批量查询,以及批量查询串行执行带来性能问题,openGemini充分利用了Go语言强大的并发处理能力,对串行查询进行并发改造,提出的自适应并行查询任务调度器,以解决串行查询的性能问题。希望本文对大家了解openGemini有所帮助。


 

openGemini官网:http://www.openGemini.org

openGemini开源地址:https://github.com/openGemini

openGemini公众号:

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

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部