分类
uncategorized

ClickHouse内幕(2)表达式计算:ActionsChain

一、ActionsChain解决什么问题?

SQL的执行是按照执行计划中的步骤有序执行的,比如以下SQL的各个步骤的执行顺序为:from -> where -> select -> order by。每个步骤都会有一些表达式,每个下游步骤产生的表达式对应的数据会作为上游步骤的输入,那么表达式是如何进行计算的呢?ActionsChain被设计用来解决这个问题。

在一个SQL中不仅select中会生成表达式,其它步骤中也会生成表达式,比如:下面的SQL中where生成了“b > 1”、“b + c”、“b + c > 2”和“b > 1 and b + c > 2”四个表达式。

query_1: select a + 1, a + 2, b > 1, b + c from t where b > 1 and b + c > 2 order by a + 1;

在以上SQL的执行过程中有几个问题:

1 where向select输出数据的时候是输出a,b,c三个表达式,还是它生成的四个表达式,还是所有?

2 where向select输出数据的时候如何尽量少的输出数据,比如:在select中有2个与a列相关的表达式,where是否需要输出2个a列?

3 where是否需要向select输出c列?

ActionsChain被设计用来统筹计算整个查询计划中所有步骤的表达式计算,并对每个步骤的表达式输出进行优化,优化的目标与原则是尽量少的向上输出数据。在下面对ActionsChain的分析中将逐一解答以上问题。

PS: 可以通过Explain actions=1 sql的方式查看执行计划各个步骤间的action情况。

二、 ActionsChain结构示意

ActionsChain是由ActionsDAG组成的DAG结构,每个步骤的输出是下一个步骤的输入吗,每个ActionsDAG是表达式列表转换成的有向无环图。对于from步骤由于是起始步骤没有输入,它的输出是整个SQL用到的所有原始列的列表,实际上我们常常忽略from步骤,直接从where开始计算。以下简单查询对应的ActionsChain如下所示。

query_2: select a, b + 1 from t wher a > 0

三、ActionsChain构建流程

上图中展示了一个最终状态的ActionsChain结构,这里介绍ActionsChain构建过程,其主要流程包含构建和裁剪两个步骤,其中构建是指生成ActionsChain结构,在生成的过程中会保留所有的表达式并输出给下游,这样生成的ActionsChain包含了很多不必要的步骤,所以需要进行裁剪,裁剪实质把整个下游不需要的表达式从输出列表里删除。从而达到尽量少的向下游输出数据的目的。

query_3: select a+1, b from t where a > 1;

可以看到where中的所有节点全部输出给了select,总共有a, b, greater(a, 1)三个列的数据需要输出给select,但是其中的greater(a, 1)是不需要,所以需要裁剪,裁剪后的ActionsChain如下:

四、表达式复用

1. 如果下游已经计算过的表达式上游可以直接复用表达式的结果,它对应的ActionsChain如下:

query_4: select a+1, b from t where a + 1 > 1

对于表达式”a + 1″ 从where处计算得到,到后来的projection阶段不在重复计算,而是可以从下游直接获取到,从而查提升询效率。

2. 如果上游需要多个相同的表达式,那么下游只需要输出一个。

query_5: select a+1, a+1 from t where a+1 > 1;

ActionsChain统筹整个查询中各个步骤的表达式计算,本着向上输出最少数据和尽量输出计算度高的表达式的原则,尽量减少了数据传输和计算,对ClickHouse性能提升有很大帮助。

版权声明:文章为作者辛勤劳动的成果,转载请注明作者与出处。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注