背景
PostgreSQL 11 LLVM JIT,目前支持tuple deform(将磁盘上的tuple转换为内存中TUPLE格式),以及表达式(select, where, 等语义中的表达式,操作符运算,UDF等)的动态编译。
对海量数据的计算(并且表达式或TUPLE DEFORM已成为瓶颈时)有加速效果。
在2016年,俄罗斯国家科学院系统编程研究所(Institute for System Programming of the Russian Academy of Sciences ,简称ISPRAS)就研究使用LLVM JIT编译器技术来提升PostgreSQL的查询执行效率,并居于postgresql 9.6发布了LLVM专版。
https://github.com/ispras/postgres
PostgreSQL官方发布PostgreSQL 11,正式整合 llvm JIT 查询优化技术。
Currently PostgreSQL's JIT implementation has support for accelerating expression evaluation and tuple deforming. Several other operations could be accelerated in the future.
Expression evaluation is used to evaluate WHERE clauses, target lists, aggregates and projections. It can be accelerated by generating code specific to each case.
优化场景
1、需要处理的数据量庞大
2、每条记录需要大量的操作符参与计算
3、需要查询的字段靠后,需要先deform tuple中前面的字段
也就是OLAP数据分析处理场景,因为这些场景中,CPU计算效率形成瓶颈比磁盘I/O还要严重。
优化分析过程
PostgreSQL的优化器通过构建树的方式来表述执行计划,所以执行器必须以递归的方式从树的最边缘节点一直往上执行。解释执行的好处是弹性,容易改写。
但是,通常解释执行比native code慢10倍,特别是在表达式非常多时。
使用JIT(just in time)编译器,生成query的native code,从而提高大批量数据处理的效率。
以下是ISPRAS列举的一个数据分析查询例子:
采用解释执行器执行查询树
针对性优化手段是尽量的减少函数切换,使用LLVM的接口可以帮你将这个部分的代码重新生成,在一个函数内完成所有的运算。
使用直接动态生成可执行代码代理递归解析执行查询树过程,优化了Filter执行效率。
动态生成可执行代码
LLVM优化代码过程
经过多轮优化,提升执行效率。
对大量数据分析的分析处理,filter或select clause的表达式越多的情况,效果越明显。
优化结果:
测试数据的结构包括32个字段,1亿条记录(阿里的测试数据:https://yq.aliyun.com/articles/66945)
另外,一般数据库支持的数据类型就有几十上百,每种数据类型都有几十上百的算子,所以说改造的工作量是非常庞大的。PostgreSQL 11已经集成 llvm 技术,避免集成llvm消耗工作量。
进一步优化
LLVM 可以提升执行效率,但是对于数据读取和解析没有并没有优势。
如果想进一步,可以采用列式存储。列式存储可以有效的提升数据压缩率,在分析查询时,避免读取冗余列,有效降低内存和磁盘I/O消耗。同时还可以和LLVM搭配使用,做到多核并行处理数据,甚至是使用现代CPU的复杂指令SIMD(Single Instruction Multiple Data)单指令计算多个数据,提升处理性能。
总结
LLVM JIT技术改造工作量大,但对聚合查询和复杂表达式的执行效率有明显提升,适合OLAP使用场景。
在OLTP场景中,对insert、update、delete没有提升作用。如果加上列式存储技术,还会降低insert、update、delete的效率。
由于时间关系,没有另行做测试分析对比