benchANT 性能榜单技术解读 Part 2:查询优化

就在上月,国际权威数据库性能测试榜单 benchANT 更新了 Time Series: Devops(时序数据库)场景排名,KaiwuDB 数据库在 xsmall 和 small 两类规格下的时序数据写入吞吐、查询吞吐、查询延迟、成本效益等多项指标刷新榜单原有数据纪录

benchANT 性能榜单技术解读 Part 2:查询优化_第1张图片
KaiwuDB 在 xsmall 和 small 两类规格下的时序数据写入吞吐数据

上一期,我们为大家详细介绍了 KaiwuDB 写入吞吐背后的 3 大核心技术。今天,我们想和大家分享 KaiwuDB 如何优化查询的独家秘籍 

01 查询吞吐优化

✅ 秘籍1:连接层优化在现代数据库中,高并发的连接管理和 I/O 操作往往是性能瓶颈的关键。特别是在时序数据库场景中,经常会有多个客户端并发向数据库写入或查询数据,而时序数据库的部署环境资源通常又比较有限,需要应对有限 CPU 和内存资源情况下的并发连接问题。多数数据库使用基于线程的方式来处理客户端的请求,例如为每个连接请求开启一个独立的线程来处理。这种方式虽然直观,但并不适用于高并发场景,因为不仅线程需要占用一定的内存资源,而且操作系统在线程之间的切换也需要一定的开销,并不适用于低资源、高并发场景。

KaiwuDB 采用多线程 Reactor 模式的连接层优化解决这一问题,实现了高效的连接处理和负载均衡。如下图所示,KaiwuDB 使用一个 Connection Handler 线程处理数据库连接请求,通过多个 Query Handler 线程组成线程池进行查询执行(如数据写入和查询等)。

benchANT 性能榜单技术解读 Part 2:查询优化_第2张图片

Reactor 模式是一种事件驱动的架构,它将服务端接收连接和事件处理分离,对于客户端的所有请求使用一个专门的线程去处理,这个线程监听是否有客户端的请求抵达,一旦收到客户端的请求,就将其分发给事件处理程序进行处理。基于多线程 Reactor 模式,KaiwuDB 将涉及到 I/O 操作等耗时的操作交由线程池中的 Query Handler 处理,帮助数据库性能得到了可观的提升。

以本次 benchANT Time Series: DevOps 的 xSmall 场景为例,数据库部署在 2 核 8GB 的硬件资源上,需要处理来自 50 个客户端连接的高并发写入和查询请求。KaiwuDB 的多线程 Reactor 在这种资源受限但负载并发度高的场景下,既充分发挥了 CPU 的性能,又避免了单线程 Reactor 在处理某个连接上的业务时,整个进程无法处理其他连接事件的弊端。

02查询延迟优化

✅ 秘籍2:查询执行流程优化

KaiwuDB 查询延迟的提升得益于查询执行流程的整体优化,首先 KaiwuDB 在合并扩展查询中进行了 Bind 和 Execute 操作,传统数据库执行用户查询有两种方式,简单查询(Simple Query)和扩展查询(Extended Query)。简单查询的输入为 SQL 原始语句,每次执行均须重新解析查询语句及构造执行计划,执行效率较低。 扩展查询则是把简单查询切分成 Parse,Bind,Execute 等几个步骤,从而复用执行计划,以获取更高的执行效率。

KaiwuDB 在支持两种 SQL 执行方式的同时,对扩展查询中的 Bind 和 Execute 操作进行了合并处理。这在很大程度上降低了查询执行的网络开销,从而获得了10%左右的查询性能提升。在性能分析时,我们发现原始的 PostgreSQL 协议在一次 SQL 查询执行过程中,需要调用多次的 socket flush 操作,这在查询执行频率较高时,会带来非常大的网络开销。

在 Reactor 连接层优化基础上,通过对 PostgreSQL 协议的优化,我们最大程度的减少了 socket flush 操作的调用次数,从而使查询性能有 8% 左右的提升。

✅ 秘籍3:聚合算子优化
聚合查询是时序数据库中常见的负载类型,特别是带有时间窗口聚合的查询,例如 benchANT Time Series: DevOps 中涉及到的“查询指定设备在指定一小时时间段内每分钟的 usage_user 的最大值”。对此类时间窗口内的聚合查询,如果在扫描数据的同时可以完成聚合操作,则可以在很大程度上提高查询的执行效率。KaiwuDB 通过对聚合算子优化,实现了将聚合算子下推到存储层,缩短了查询执行链路、降低了数据遍历代价和数据传输开销。

如下图所示,优化前,KaiwuDB 需要在读取数据的 tag 信息后,遍历 metrics 数据并且传输到聚合算子,再在聚合算子中进行聚合操作;而优化后,聚合算子直接下推到存储层,在扫描 metrics 数据的同时,完成时间戳改写、Groupby 判别以及聚合操作。通过聚合算子下推,KaiwuDB 的执行延时获得了 1.5 倍的加速比,大大提升了查询执行性能。
benchANT 性能榜单技术解读 Part 2:查询优化_第3张图片
与此同时,针对时序数据的特点,KaiwuDB 进一步优化聚合算子的执行流程,实现了有序 Scan 算子,可以高效地读取时序数据,并生成有序结果集。在此基础上,实现了“数据扫描聚合融合算子”(AggTableScanOP),在扫描时序数据的同时完成数据聚合,使得时序数据的聚合性能提升了 40%~50%。
benchANT 性能榜单技术解读 Part 2:查询优化_第4张图片

✅ 秘籍4:无锁时间字符串转换优化
KaiwuDB 使用 PG 编码协议,在将内部时间戳数据编码为 PG 编码时,需要将时序引擎中 timestamp 类型的转换为字符串返回,其中涉及到 gmtime_r(&sec, &ts) 函数(将 time_t 类型转换为带有年月日等信息的 std::tm 类型),但 gmtime_r 需要对操作系统的时区文件加锁(感兴趣可参考https://stackoverflow.com/questions/53889107/why-does-gmtime-r-call-tz-convert-which-grabs-a-global-lock),在高并发情况下,锁操作对查询性能产生较大影响。如下图所示,在优化前,使用 profiling 工具观测到的编码为 PG 编码的 CPU 开销约为17%,其中,gmtime_r 的锁操作占比较高。
benchANT 性能榜单技术解读 Part 2:查询优化_第5张图片
对此,KaiwuDB 实现了无锁版本的时间字符串转换优化,不再通过访问操作系统的时区文件获取闰秒等信息,而是直接在优化后的函数内计算时间戳对应的年、月、日等信息,避免了高并发情况下访问操作系统时区文件锁机制带来的性能影响。在优化后,profiling 的结果显示编码过程的 CPU 开销占比大幅下降,由于gmtime_r 的锁操作造成的 CPU 开销被优化。
benchANT 性能榜单技术解读 Part 2:查询优化_第6张图片

你可能感兴趣的:(数据库)