简介: 作者| 魏闯先阿里云数据库资深技术专家

一、ADB PG 和Laser 计算引擎的介绍

(一)ADB PG 架构

ADB PG 是一款云原生数据仓库,在保障事务ACID 能力的前提下,次要解决云上海

量数据的实时剖析问题。它的架构与传统的MPP 数据仓库十分相似,次要分成两层,第一层是master 节点;第二层是work 节点。

master 节点次要承当实时写入和事务的解决,执行打算的生成。与其余的传统的

MPP 数据仓库不同的是ADB PG 的master 节点反对线性扩大,能够通过多个master

晋升整体的事务能力、实时写入吞吐能力。

work 节点次要承当两个性能,第一个性能是执行,第二个性能是存储。执行引擎采纳

的是向量化执行引擎,通过向量列式Batch 解决,codegen 技术,以及Fusion Scan 减速列式计算效率,在一些剖析场景性能绝对于一般的火山模型有了3~5 倍的晋升。

同时它的存储节点不仅反对传统的行表和列表,也能够通过表面形式反对一些开源的表

构造,例如Parquet、ORC 等开源数据结构。ADB PG 能够间接剖析保留在相似于像

OSS/HDFS 等分布式存储上的数据,缩小数据的导入,能够大幅的升高用户的应用门槛和存储老本。

(二)为什么做Laser 计算引擎

为什么不采纳PG 原生的计算引擎?

第一,PG 是一个传统的事务型数据库,它次要的优化大多来自于TP 的事务优化,并没有针对海量数据的剖析计算做定制化的优化。

第二,PG 计算引擎采纳解释执行的逻辑,简单表达式采纳函数执行树的递归的调用解

释执行。如图中的例子所示,每个表达式都被翻译成一个函数并组成一个执行树。每一条的数据都通过以上的函数递归调用去实现最终的计算。它带来的问题就是在海量千万以上的数据计算场景,虚函数调用大幅影响计算的性能。

第三, PG 默认只反对行存存储引擎,并不反对列存,所以它的整个计算执行过程是逐行解决数据,并没有对列存做定制化的优化。

第四, PG 代码具备十分好的扩展性、兼容性,然而在性能上思考不多。例如说在计算过程中会波及到内存的屡次拷贝,序列化的开销比拟高。

最初,PG 采纳的是单分区单过程执行模式,无奈充分发挥古代多核CPU 的劣势。

(三)支流OLAP 业界计划

在开始ADB PG 计算引擎的选型过程,咱们重点调研了以后支流的OLAP 业界支流

计划。

次要分成两大类,第一类:向量化执行;第二类:编译执行。

第一:向量化执行的根本做法,十分相似于火山模型,次要差异来自于它采纳的是批量计算,每一批里优先列式计算。

这种模式劣势在于能够充分发挥CPU 的流水线执行和内存的程序拜访,缩小cache

的miss。毛病是第一实现逻辑比较复杂。第二,它须要批量的数据,并不适宜每次计算数量较小的OLTP 场景。第三,它须要缓存批量数据,缓存自身带来肯定的内存开销。

第二:编译执行根本做法是应用Codegen 技术,将所有的算子编译成函数,通过PUSH 的模型自下而上通过数据上推实现计算。

长处一:因为每次计算的都是一行数据,执行过程能够将这一行数据保留在寄存器外面,寄存器计算代替内存计算。长处二,它通过Codegen 技术把简单的算子编译成一个函数,所以它非常适合计算复杂性十分高的计算减速。

毛病在于,PUSH 模型管制逻辑比较复杂,同时因为采纳单条计算,无奈做到内存的程序拜访,所以它整体的Cache miss 率比拟高。典型的代表产品有Spark 和 Peloton。

ADB PG 综合思考这两类计划的优缺点,最终应用了向量化的计划,次要思考到ADB PG 原生PG 火山模型与向量化模型架构上较为靠近,革新成向量计算引擎的逻辑顺畅,革新老本较编译执行小。

(四)业界支流计算引擎比照

咱们对业界支流开源计算引擎做了比照,包含ClickHouse、PG11、Spark、ADBPG。在执行模型上,ClickHouse 和ADB PG、PG11 都采纳的向量执行,Spark 采纳

的是编译执行。

在内存模型上,ClickHouse 采纳的是列存、PG11 采纳行存、Spark 采纳行存、ADB PG 采纳行列混存。行列混存次要利用在相似于join、AGG 的场景,咱们能够将多列group by、hashtable 数据拼成一列数据,能够充分发挥程序拜访的效率。

在即时编译上,ClickHouse 采纳表达式级LLVM、PG11 采纳表达式级LLVM,Spark 采纳Stage Java 技术,ADB PG 采纳算子级LLVM 技术。算子级LLVM 技术能够晋升算子的计算性能。

在硬件加速上,ClickHouse 和PG11 都不反对硬件加速,Spark 反对FPGA 减速,ADB PG 采纳IR 技术,能够通过将IR 翻译成对应的机器执行代码,从而反对GPU 减速。

二、laser 计算引擎的核心技术

Laser 计算引擎的核心技术次要包含5 大块:

  1. 向量计算引擎
  2. 行列式内存模型
  3. JIT 减速
  4. SIMD 指令减速
  5. FUSION SCAN

第一,向量计算引擎,传统火山模型中算子之间数据逐条交互,向量化计算引擎之间的交互的是BATCH 数据,而后在每个算子外部,采纳的列式多条数据并行计算,这种逻辑能够充沛的施展CPU 流水线的作用。

在内存模型上,咱们采纳的是行列混存内存模型。在算子之间数据传递的是一个mini batch,mini batch 外部采纳的行列混存的构造。因为每列数据在内存里都是间断摆放的,所以每次计算一列都是内存的程序拜访的过程。

第三,针对简单计算,采纳JIT 技术减速。能够利用LLVM CodeGen 技术将简单计算过程转换成IR 代码,而后再通过IR 代码翻译成机器码。它的益处是能够防止类型判断,缩小虚函数的调用,从而晋升计算性能。

第四,针对一些简略场景(如:聚合场景、固定场景),利用古代CPU 的SIMD 指令,实现单条指令多条数据的并行执行,大幅晋升这些简略场景的效率。

第五,针对列存场景,能够通过FUSION SCAN 去缩小无用列读取,防止无用内存的两头拷贝,从而晋升列表的计算性能。

(一)向量计算引擎

下图是一个典型的火山模型下SUM 算子的计算过程。对于火山模型,如果总共有n条数据,就会调用n 次的函数调用。左边是向量化执行过程,sum 函数接管输出参数是一个数组,而不是两个变量。整个执行过程,数据按2048 条分批解决,每2048 条数据调用一次sum 函数。

从这个例子中显著能够看出:

第一,Sum 函数调用从原来的n 次变成n÷2048,缩小了屡次。

第二,在函数外部解决中,因为计算的数据是一个batch,就能够充分发挥SIMD 指令减速成果,实现单条指令多条语句的并行计算。

第三,能够针对一些算子,如AGG 和JOIN,能够将AGG 和JOIN 算子函数合并一个函数,能够进一步的缩小虚函数调用,晋升零碎性能。

因为计算过程中全副采纳数组计算,能够将计算过程中的数组应用内存池化技术治理。通过MemoryPool 能够实现定长数据的内存的复用,防止频繁内存调配和开释,缩小整个内存的碎片。在理论的TPC-H 的测试中,应用向量化引擎后,Q1 晋升了120%,Q18晋升了190%。

(二)SIMD指令减速

针对简略的减速,能够利用古代CPU 的SSE、AVX 指令,一条指令能够实现512bit 数据计算。

咱们对TPCH 测试中的Lineitem 表做性能的比照测试,在应用SIMD 当前,整体的性能从原来的1 秒多升高到了200 多毫秒,有了4 倍左右的晋升。

(三)Just-in-Time 编译优化

ADB PG 不仅反对表达式级的CodeGen,也反对算子级的CodeGen。每个plan的node 对应一个CodeGen 单元和一个Executor,CodeGen 单元依据plan node 生成code(IR),Executor 依据硬件平台抉择不同的后端,将IR 生成对应的执行文件,并申请资源执行,最终的后果通过master 返回给客户端。

如图所示,对于这样一个简略的表达式,where a>10 and b<5,如果采纳解释执行,总共包含三次函数调用,1、a>10;2、b<5;3、and 函数。

如果应用LLVM GIT 编译优化,下面的三个函数就编译成三条LLVM 指令,防止了三次函数调用的开销。

在TPCH 测试场景中,应用JIT 减速后整体的性能晋升了20%~30%,并且在测试中发现,表达式越简单,性能晋升越显著。

(四)Fusion Scan 优化

Fusion Scan 次要优化是缩小无用列的读取,并且尽量的缩小无用数据的读取和内存的拷贝。

举个例子,如果要查问满足a 大于3 和b 小于6 的a,c*d 的值,传统做法是对数据库中的每条数据数据,做a 大于3 和b 小于6 的条件过滤并且计算对应列的值。

Fusion Scan 的做法分成两阶段:

第一阶段是对过滤列做计算。把a 列和b 列的所有数据读出来,对每条数据进行判断。如图所示,满足条件的只有第一行第三行,咱们把第一行第三行号保留在一个bitset中,同时把第一行和第三行的a 列值也保留在mini batch 中;

第二阶段是计算project 列,因为满足这个条件只有第一行和第三行,咱们只须要把c 列和d 列的第一行和第三行的值读取进去。同时为了防止两头后果的数据拷贝,咱们间接去将c 列和d 列的值后果相乘,把后果保留在mini batch 的第二列中。

在计算过程中,咱们提前将表达式编译成IR 代码,能够防止了屡次表达式函数的递归调用。

以上过程的次要优化点在于:

第一、防止无用列表D、E、F、G 列读取;

第二、实现了按需读取,只有满足条件的c 列和d 列的外面内容才进行计算和IO,不须要读那些不满足条件的数据。同时在c 和d 计算过程中,间接进行c 和d 的读取,无需内存两头后果的拷贝。

在理论执行过程中,Fusion Scan 联合列存块block 索引做进一步的优化。block

索引中蕴含了数据块的min 和max,咱们能够将min 和max 值和where 条件做交加,

只有这个交加非空的话,才会去真正读取block 的值,否则能够间接跳过这个block。

通过Fusion Scan 的技术,在列存的场景Scan 算子整体的性能有3 倍以上的晋升。

(五)算子实现-HashJoin

HashJoin 的向量化执行引擎,算法采纳Hybrid Hash Join,HashTable 采纳凋谢链表数据结构。

HashJoin 的实现过程,次要包含:

  1. 把左表probe 列的值取出来计算它的Hash 值。
  2. Hashcode 的值去模entry 个数,获取对应的行号。
  3. 对应行号里的所有的entry 对象,比拟它的哈希值,如果哈希值雷同,再去比拟join key。
  4. 如果join key 雷同,则代表probe 胜利,拼接左右表的对应列并生成最终的后果。

如何将这样的执行过程用向量化实现?

  1. 从左表外面读取批量数据。
  2. 应用CodeGen 技术批量计算hash code 值。
  3. 依据hashcode 值,批量查找hash table,失去可能的后果集。
  4. 批量比拟左右表的join 列值,如果匹配的话,则拼接左右表的对应列并生成最终的后果。

与原来行式的火山模型比起来,向量化执行次要差一点在于:

  1. 按列计算;
  2. 批量计算。

(六)插件集成

计算引擎如何与ADB PG 代码交融?

ADB PG 同时反对PG 计算引擎和Laser 向量化计算引擎。优化器会主动依据SQL 的pattern 和扫描的数据量来决定是否应用Laser。如果扫描数据量太少,则应用原生的计算引擎。如果数据量足够多,并且这些SQL pattern 比拟适宜应用向量化执行引擎的,就应用laser 计算引擎。

Laser 引擎的所有代码采纳插件模式,代码独立。益处在于代码能够和原生代码之间齐全是松耦合关系,不会影响PG 的原生代码,同时能够复用外面的一些函数和数据结构。插件模式还带来一个益处,就是能够实现热降级。因为采纳动静库形式,可能在不重启PGdameon 过程的状况下,替换插件,实现降级LASER 引擎。

惟一须要批改的是三个stub 函数—ExecutorStart、ExecutorRun、ExecutorEnd。

(七)TPC-H 后果

2020 年5 月20 号,咱们实现了TPC-H 30TB 场景测试,拿到了世界第一的问题。相比于第二名微软SQL Server 2019,整体性能晋升了290%,且老本只有SQL

Server 的1/4。

通过性能指标统计,Laser 计算引擎对性能晋升起了至关重要的价值,绝对于PG 计算引擎,性能晋升了两倍之多。细分计算引擎的各种优化,其中大半的性能晋升都是来自于向量化晋升。其次是是JIT 减速,次要来源于表达式的计算。第三来自于是Fusion Scan,针对列存场景下,咱们通过Fusion Scan,缩小了内存的拷贝,缩小了无用的读取。最初还有小局部来自于SIMD 指令的晋升。

三、计算引擎的将来瞻望

整体的将来转化(以将来一年为打算):

第一:2020 年12 月,反对窗口函数,实现全算子的向量化革新。

第二:2020 年3 月,实现网络motion 重构。

第三:2020 年6 月,实现算子并行执行优化,能够充分利用多核能力。

第四:2020 年9 月,实现优化器适配。优化器不仅适配打算数据书,同时可能依据计算引擎来做动静辨认,可能感知到数据的动态变化,再去动静去调整执行打算。

原文链接
本文为阿里云原创内容,未经容许不得转载。