随着数据库软硬件技术的发展,经典的 SQL 计算引擎逐渐成为数据库系统的性能瓶颈,尤其是对于涉及到大量计算的 OLAP 场景。
如何充分发挥底层硬件的能力,提升数据库系统的性能,成为近年来数据库领域的热门研究方向,而向量化执行就是解决上述问题的一种有效手段,本文主要对向量化技术的原理及优点进行简单的介绍。
为什么数据库需要向量化?
MPP数据库的API(Application Programming Interface)或者命令行接收到了SQL查询请求之后,系统先经过查询解析,然后进行查询优化,通过任务调度执行从存储引擎里面把数据读取出来,计算出结果集,返回给客户。
一个查询语句经过词法分析、语法分析、语义检查后生成的结果叫做Query Tree,经过优化器之后的结果叫做Plan Tree。
传统数据库执行查询计划通常采用火山模型的方式,流程如上图所示。
火山模型具有简单、直观、易用等优点,早期数据库受限于硬件水平,IO、内存和CPU资源都非常昂贵,火山模型能够极大缩减内存使用量,因而被各大厂商普遍采用。
如今,随着硬件技术的不断发展,火山模型的弊端也逐渐凸显。这种方式存在重复性执行多、反序列化代价高、数据局部性差等缺陷,而且一次执行仅处理一行数据,CPU花费大量时间在遍历查询操作树上,同时也没有针对CPU的SIMD能力等特性做优化,从而造成查询执行效率低下的问题。
据我们在PostgreSQL上实际测试,对于select sum(a) from table这样的查询,火山模型在执行查询计划时,大部分时间用于读取数据、对数据的反序列化、遍历执行树等操作上,用于实际SUM运算的时间不足4%。
为了进一步提升SQL计算引擎的性能,数据库执行器领域出现向量化和编译执行的新技术。这两种技术的出现都是为了提升性能,更准确地讲是为了提升 CPU的运行性能。
编译执行是把复杂运算编译成一个函数,重复调用得到结果。编译执行的优点是可以减少分支判断,并使函数调用栈变浅。
向量化执行指的是将一次计算一条元组的形式,转换为一次计算多条元组的向量化计算。通过实现批量读取和处理,大大精简了函数调用开销,减少了重复运算,增加了数据的局部性,提高了执行效率。
HashData向量化的实践
对于像HashData这样采用云架构的数据仓库而言,向量化可以通过提升单节点的执行能力,使整个集群的运算性能得到很大提升。列存数据的高压缩比不仅节约了存储空间,同时在向量化运算过程中也有着天然的性能优势。
HashData在实现向量化的过程中,引入了Apache 软件基金会开源项目Apache Arrow。Arrow 定义了标准的方式来表示可有效处理的内存数据,同时支持多种流行的编程语言中,包括 Java、C、C++ 和 Python等。
Apache Arrow的子项目Gandiva提供了编译执行向量化运算的可能,在应用于数据库表达式计算时,相对于解释执行的向量化运算也有明显的性能优势,但是由于百毫秒量级的编译时间,不利于小数据量查询,因此需要在优化阶段根据数据情形决定是否使用。
为确保分布式数据库的底层数据的稳定传输,Arrow提供了基于gRPC的进程间通信Flight,其允许数据以Batch的形式同时进出服务器集群,让开发人员可以更轻松地创建可扩展的数据服务。
根据我们在PostgreSQL单机测试的结果,在使用Arrow做向量化执行后,ORC数据格式+向量化,相对于heap表加+行引擎,在最好的情形下可以获得30倍以上的数据性能提升。
数据库的向量化不仅仅是数据存储和运算的向量化,还是一个巨大的性能优化工程。未来,HashData会持续优化、完善向量化执行,提升系统性能,更好地满足客户业务需求。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。