AP计算-查询编译
date
slug
tags
summary
type
status
Efficiently Compiling Efficient Query Plans for Modern Hardware
该文章首先提出了pipeline的定义:pipeline意味着数据的处理可以直接在寄存器中进行,不需要重新搬回内存。如果多个算子可以形成一个pipeline,处理速度会大大增加。而火山模型和batch模型都无法实现这个目标。因此,该文章解决的关键问题在于:提出一种利用编译的执行模型,尽可能使多个算子形成pipeline。
首先,该文章定义了pipe breaker,pipe breaker即算子需要将数据物化到内存,比如join。通过pipe breaker,将执行计划分割成多个pipeline。
而对于同一个pipeline的算子,在执行的时候会被编译在一起形成一个代码块,该代码块可以实现在寄存器中完成对数据的处理。这听起来很神奇,这篇文章提出了一个直观的方法来实现这个目标。
假设我们有如上的执行计划,并且采用如下伪代码的传统火山模型执行模式:
当我们展开真正的执行栈,其会类似下面所示,可以看到实际的数据处理路径。
因此,如果要将以上三个算子展开成一个代码块进行执行,它大概率会长成上面有效数据处理路径的样子。
很自然这种样子是一种push模式,而非pull模式
那么如何生成长成有效数据处理路径的代码?一个简单的想法是,将以上
do_*
换成print do_*
,即如果将
print do_*
进一步换成print <do_*中的内容>
,就可以生成一个完整的没有函数跳转的代码块,其行为和之前的数据处理是一致的。这种方法正是该文章中提出的方法,它将
next
方法重新命名为produce
,print *
则,命名为comsume
。如文中例子所示:这种方法被后续一些系统采用,比如spark: https://github.com/apache/spark/pull/10735
Loading...