2数据库向量化的挑战
数据库向量化的挑战主要有以下几点:
1. 全面的列式布局:在磁盘,内存,网络中全部都是列式布局,这意味存储引擎和计算引擎的完全重构2. 所有算子、表达式和函数支持向量化:这意味数人年的工作3. 算子和表达式计算尽可能使用 SIMD 指令:这意味着大量 Case By Case 的细致优化4. 重新设计内存管理:因为处理的数据从一行变成了数千行5. 重新设计数据结构:比如 Join、Aggregate、Sort 等核心算子的数据结构都需要进行改变
6. 整体性能提升 5 倍以上:所有的算子和表达式性能都要提升 5 倍以上,意味着全面地、系统地性能优化,所有重要的算子和表达式性能都不能有短板
3算子和表达式向量化的关键点
数据库的向量化在工程上主要体现在算子和表达式的向量化,而算子和表达式的向量化的关键点就一句话:Batch Compute By Column, 如下图所示:
对应 Intel 的 Top-down 分析方法,Batch 优化了 分支预测错误和指令 Cache Miss,By Column 优化了 数据 Cache Miss,并更容易触发 SIMD 指令优化。
Batch 这一点其实比较好做到,难点是对一些重要算子,比如 Join、Aggregate、Sort、Shuffle 等,如何做到按列处理,更难的是在按列处理的同时,如何尽可能触发 SIMD 指令的优化。每个算子的按列处理和 SIMD 指令优化我们会在之后的 《StarRocks 查询源码解析》系列文章中详细解释。
4数据库向量化如何进行性能优化
前面提到,数据库向量化是一个巨大的、系统的性能优化工程,两年来,我们实现了数百个大大小小的优化点。我将 StarRocks 向量化两年多的性能优化经验总结为 7 个方面 (注意,由于向量化执行是单线程执行策略,所以下面的性能优化经验不涉及并发相关):
1. 高性能第三方库:在一些局部或者细节的地方,已经存在大量性能出色的开源库,这时候,我们可能没必要从头实现一些算法或者数据结构,使用高性能第三方库可以加速我们整个项目的进度。在 StarRcoks 中,我们使用了 Parallel Hashmap、Fmt、SIMD Json 和 Hyper Scan 等的第三方库。
2. 数据结构和算法:高效的数据结构和算法可以直接在数量级上减少 CPU 指令数。在 StarRocks 2.0 中,我们引入了低基数全局字典,可以通过全局字典将字符串的相关操作转变成整形的相关操作。如下图所示,StarRcoks 将之前基于两个字符串的 Group By 变成了基于一个整形的 Group By,这样 Scan、Hash 计算、Equal、Memcpy 等操作都会有数倍的性能提升,整个查询终会有 3 倍的性能提升。
3. 自适应优化:很多时候,如果我们拥有更多的上下文或者更多的信息,我们就可以做出更多针对性的优化,但是这些上下文或者信息有时只能在查询执行时才可以获取,所以我们必须在查询执行时根据上下文信息动态调整执行策略,这就是所谓的自适应优化。下图展示了一个根据选择率动态选择 Join Runtime Filter 的例子,有 3 个关键点:
a. 如果一个 Filter 几乎不能过滤数据,我们就不选择;
b. 如果一个 Filter 几乎可以把数据过滤完,我们就只保留一个 Filter;
c. 多只保留 3 个有用的 Filter
4. SIMD 优化:如下图所示,StarRcoks 在算子和表达式中大量使用了 SIMD 指令提升性能。
5. C++ Low Level 优化:即使是相同的数据结构、相同的算法,C++ 的不同实现,性能也可能相差好几倍,比如 Move 变成了 Copy,Vector 是否 Reserve,是否 Inline, 循环相关的各种优化,编译时计算等等。
6. 内存管理优化:当 Batch Size 越大、并发越高,内存申请和释放越频繁,内存管理对性能的影响越大。我们实现了一个 Column Pool,用来复用 Column 的内存,显著优化了整体的查询性能。下图是一个 HLL 聚合函数内存优化的代码示意,通过将 HLL 的内存分配变成按 Block 分配,并实现复用,将 HLL 的聚合性能直接提升了 5 倍。
7. CPU Cache 优化:做性能优化的同学都应该对下图的数据了熟于心,清楚 CPU Cache Miss 对性能的影响是十分巨大的,尤其是我们启用了 SIMD 优化之后,程序的瓶颈就从 CPU Bound 变成了 Memory Bound。同时我们也应该清楚,随便程序的不断优化,程序的性能瓶颈会不断转移。
下面的代码展示了我们利用 Prefetch 优化 Cache Miss 的示例,我们需要知道,Prefetch 应该是后一项优化 CPU Cache 的尝试手段,因为 Prefetch 的时机和距离比较难把握,需要充分测试。
#04StarRocks 向量化工程的粗浅思考
—