向量化执行引擎
在三种常见的数据库查询引擎执行模型中我们讲到了向量化执行引擎本质上是一种批处理模型。批处理思想在计算机的世界里经常闪闪发光。高并发场景中,可以把大量的请求合并,改为调用批量接口;大数据下读取分布式文件系统时,如果要读取大量的小文件,可以将这些小文件打成tar包,或者批量一次打开100~500个文件;数据库插入数据时,修改单条插入为批量插入等。批处理减少了cpu的中断次数,可以更加合理的利用资源。
在向量化执行引擎模型中,列式存储占据着天然的优势:
1、压缩能力的提升。同一列的数据类型相同,压缩比高。
2、IO总量小。压缩减少了一部分IO,另外投影操作时,只需要读取查询的字段。
3、支持对某一列进行向量计算
通常向量化执行引擎都是用在OLAP数仓类系统。而OLTP系统,由于使用行存,并且点查询居多,所以向量化执行的优势也很难体现出来。
两种向量化执行引擎的实现
方法一:仍使用火山模型,将一次一tuple的处理模式,修改为一次向上返回一组列存行值(例如:100-1000行)处理方式。
compare-row-column
图1中描述的就是火山模型实现的行存执行引擎与列存执行引擎,其中左边代表的是传统的行存火山模型,右边代表的是列存实现的火山模型。
火山模式是从执行计划树的根节点开始向叶子节点递归调用,然后由叶子节点扫描节点,过滤出符合条件的tuple 给上层节点处理,AGG算子缓存中间结果。
右边列存执行引擎,执行逻辑基本上与左边行存执行引擎一致,但是每次扫描处理的是一组列数据集合。这样每次处理的数据变多,总体的调用次数变少,CPU的利用率得到了提高。
方法二:将整个模型改造成为层次型的执行模式,也称编译执行模型。
compare-batch
整个执行计划树从跟节点到叶子节点只需要调用一次。从叶子节点开始每一层都是执行完所有的操作之后,才向上返回结果。
编译执行模型的缺点就是每一个节点都需要将数据进行缓存,在数据量比较大的情况下,内存可能放不下这些数据,需要写盘。
• 拉取模型 vs 推送模型
方法一的向量化执行是自上而下的批量拉取模型;方法二的编译执行是自低向上的推送模型。
原则上这两个模型是不相容的,二者只能取其一。但是也有人在尝试编译执行融合向量化:把查询树分解,部分用向量化方式,部分用编译执行方式。
以上为两种向量化执行引擎的实现方法,「分布式技术专题」是国产数据库hubble团队精心整编,专题会持续更新,欢迎大家保持关注。