作者: 康凯森
日期: 2023-04-05
分类: OLAP
对一个数据库产品来说:
对一个数据库工程师来说:
从应用视角,主要是 Latency 和 Throughput。 (在总资源不变的情况下 缩短响应时间,一般都可以提升吞吐率。)
从系统资源的视角,我们要优化 CPU, IO, Memory, NetWork 等系统资源的利用率。 (在性能优化的过程中,我们在关注查询吞吐和时延的同时,也一定要关注系统资源的利用率。因为有时候的性能提升几倍的同时,也多用了几倍的 CPU)
一方面可以通过数据库系统内置的性能优化工具或者可观测性工具去找到瓶颈点,另一方面可以通过 Linux 通用的性能测试工具来寻找瓶颈点。
如上图所示,查询 Profile 是我们发现性能瓶颈点最常用的工具,从 Profile, 我们可以知道一个查询是慢在 plan 阶段,还是执行阶段,也能知道是哪个算子是执行瓶颈
如上图所示,我们通过一个命令就可以知道 StarRocks 优化器到底慢在哪一个阶段,可以快速定位出优化器阶段的性能瓶颈。
如上图所示,我们可以通过 StarRocks 的执行器的 trace 工具快速定位出执行层到底是慢在哪个点,比如是CPU的问题,IO的问题,还是调度框架的问题。
除了数据库系统自身的工具,我们也可以使用 Linux 通用的性能 profile 工具,比如,最常见的性能 Profile 工具,Perf,可以通过火焰图看成 CPU 热点。 详情大家可以参考: https://www.brendangregg.com/perf.html
很多时候,性能的瓶颈并不是在 CPU 执行本身,而是在 IO,网络,Lock 上,这时候我们就需要进行 Off CPU 分析,而且这时候基于 Sampling 的性能工具往往没有效果,我们需要使用基于 Trace 的 性能工具,比如 eBPF。详情大家可以参考 https://www.brendangregg.com/offcpuanalysis.html
如上图所示,Intel 基于 CPU 执行的整个过程,提出了 《Top-down Microarchitecture Analysis Method》的 CPU 微架构性能分析方法,将 CPU 执行的可能瓶颈点分为4大类,然后每一类在不断细分,层层深入,定位到最具体的性能瓶颈点。
为了便于大家理解,我们可以将上图简化为下图(不完全准确):
即影响一个 CPU 程序的性能瓶颈主要有4大点:Retiring、Bad Speculation、Frontend Bound 和 Backend Bound,4个瓶颈点导致的主要原因(不完全准确)依次是:缺乏 SIMD 指令优化,分支预测错误,指令 Cache Miss, 数据 Cache Miss。
如上图所示,操作系统每个模块的问题都有对应的工具可以进行分析,大家在日常工作中就需要不断积累,清楚哪类问题可以用哪些工具解决,也要清楚每个重要工具可以解决哪些问题。
这一点上 TIDB 做的比较好,整个查询过程的关键性能指标都暴露出来,可以比较方便的分析某类问题的性能瓶颈,主要是对DBA,解决方案,普通用户更加友好。 详情可以参考 https://docs.pingcap.com/tidb/dev/performance-tuning-methods
SQL 是声明式,只告诉了 What,没有告诉 How, 所以一个 SQL 的执行路径可能成千上万,优化器选择出的最终 Plan 往往不是最优的,我们研发有时候也不能判断哪种执行计划是最优的。 主要是两个原因: 1是执行计划很多,人很难枚举,2是执行计划的真实执行性能是和执行器每个算子的性能,集群规模,数据特点,硬件资源等都有关系。 所以我们需要有专门的优化器 Plan 测试工具去枚举测试 不同执行计划的真实性能,从而发现更优的执行计划。
如上图所示,上面两个SQL 等价,但是很多数据库的对于第二个SQL 却无法推断出 ename not like 'ACCT'
这个谓词, 导致有3倍的性能差距。
下面两个 SQL,如果有 emp_pk 是主键的信息,group by emp_pk 也可以直接优化掉,性能就可以提升3倍。
如上图所示,数据库也是一个大型的 CPU 应用,所以我们可以先按照所有 CPU 应用的通用优化思路去优化数据库的查询性能,比如自底向上我们依次可以从这些点进行优化:
这一点我在 如何打造一款极速分析型数据库:预计算 VS 现场计算 已经解释的比较清楚。
具体到数据库层面的优化,我们可以分为 High Level 和 Low Level 的两大类优化。 High Level 的优化主要包括:
这一点大家可以参考我之前在 StarRocks 技术内幕:向量化编程精髓 的分享,之后的每一个点我也会在 OLAP 性能优化指南 详细展开描述
性能优化的本质就是优化各种系统资源的使用。我们针对查询优化的各种手段,其实本质上都是在优化 CPU, 内存,IO,网络等系统资源的使用:
如果我们解决一个问题的算法复杂度相同,那么谁的实现更优,就是看谁做的无用功更少,使用的系统资源更少。
上图就是一个查询执行层优化网络的各种优化手段的示例。
答案是 性能优化永无止境 ,因为
很多时候,我们的性能测试都是在标准环境进行,都尽可能屏蔽噪音,但是在生产环境,要想取得在 Benchmark 中的性能数据,我们可能还要再付出10倍不止的精力:
在生产环境中,上面的每一个问题都不是很好解决,都是一个大型的优化项目。
在考虑要不要进行一个性能优化时,我们还需要从下面几点进行权衡:
我们永远都要有这样一个意识:
1 Serverless 架构下面向成本的性能优化:
参考 如何打造一款极速分析型数据库:ServerLess 之极致弹性 要想在 Serverless 架构下取得很好的性能,我们的整个架构,执行框架,算法实现上就不能单点和串行,必须保证每个S QL 都可以随着节点数增多性能可以获得成比例提升,其次,我们也必须解决数据倾斜问题,否则,就无法充分利用整个集群的资源。
2 真实业务场景的自适应执行优化:
基于不同的数据分布,数据技术,数据基数,数据相关性,优化器很难保证任何时候都产生比较好的plan,所以自适应执行的优化不可避免,可以参考 数据库之美 —— 查询自适应执行
3 真实历史数据的 AI 优化
性能优化是一门工程,实践出真知,大家还是多动手,多尝试,多积累经验。也欢迎大家专注 OLAP 性能优化指南 ,给个 Star,我会持续完善更新,也欢迎大家共建。