详解数仓的向量化执行引擎

💡 原文中文,约2900字,阅读约需7分钟。
📝

内容提要

本文介绍了GaussDB(DWS)中的向量化执行引擎,该引擎采用一次一批元组的执行模式,能够减少遍历执行节点的开销,提高CPU的有效利用率。向量化引擎与列存储结合,能够在底层扫描节点装填向量化的列数据。文章还介绍了行执行器和列执行器的区别,以及向量化引擎的性能优势。最后,文章提到了GaussDB向量化引擎的演进过程,包括Sonic向量化引擎和Turbo向量化引擎的推出,以及对各种算子的进一步优化。

🔎

延伸解读

行列存储与执行引擎的匹配逻辑

文章指出,行存表按行存储tuple,适用于TP场景,数据频繁更新且查询涉及多列;列存表按列存储,适用于AP场景,表列数多但访问列数少,能减少IO并提高压缩比。向量化引擎与列存天然结合,在底层扫描节点装填向量化列数据,从而发挥OLAP性能优势。这种匹配关系解释了为何列存需要配套向量化执行引擎,而非简单替换行引擎。

向量化性能提升的关键机制

向量化引擎采用一次一批元组(Batch,约1000行)的执行模式,相比行执行器一次一tuple,减少了遍历执行树和函数调用的开销。文章以表达式x*(1-y)为例,列存Cstore Scan比行存Seq Scan耗时减少85%。其性能优势源于:批量读取减少IO次数、提高CPU缓存命中率、减少上下文切换,以及与列存配合减少tuple deform(列数据重构为元组)的时间开销。

行列混合执行与Adapter算子

列存表的某些场景不支持向量化执行引擎,例如string_to_array、listagg、string_agg等操作。GaussDB具备行列引擎自动切换能力,通过Adapter算子实现混合执行。对于列存数据,若只有行引擎,通常需要将列数据重构成tuple再逐行处理,这一tuple deform过程会影响查询性能。因此,行列混合机制在保持兼容性的同时,尽量让适合的算子走向量化路径。

向量化引擎的持续演进方向

GaussDB向量化引擎从第一代演进到Sonic和Turbo。Sonic对HashAgg、HashJoin等算子进一步向量化,根据列类型使用不同Array进行计算;Turbo在Sonic基础上对大部分算子向量化,并新增Null优化、大整数优化、Stream优化、Sort优化等。此外,演进还包括Stream算子与分布式框架、SMP节点内多线程并行、LLVM JIT编译消除tuple deform瓶颈,整体围绕OLAP性能提升展开。

❓

Q&A

GaussDB中的向量化执行引擎有什么特点?

GaussDB中的向量化执行引擎采用一次一批元组的执行模式,减少遍历执行节点的开销,提高CPU利用率,并与列存储结合优化OLAP性能。

行存表和列存表有什么区别?

行存表按行存储,适用于TP场景;列存表按列存储,适用于AP场景,减少IO操作并提高数据压缩比。

向量化执行引擎如何提升性能?

向量化执行引擎通过一次处理一批数据,减少函数调用和上下文切换,提高CPU缓存命中率,从而显著提升性能。

GaussDB向量化引擎的演进过程是怎样的?

GaussDB向量化引擎经历了Sonic和Turbo的演进,持续优化性能,增加了对多种算子的支持和优化。

向量化执行引擎的执行算子有哪些?

向量化执行引擎的执行算子包括控制算子、扫描算子、物化算子和连接算子等。

GaussDB如何支持行列混合执行?

GaussDB支持行列混合执行,能够根据场景自动切换行引擎和列引擎,以优化性能。

🏷️

标签

➡️

继续阅读