跳转至

6.4 查询执行

截至目前,我们讨论的都是单个关系代数操作的执行算法。现在我们需要考虑,对于一个涉及多个算子的查询计划树,我们应该怎样去执行。一个最简单的策略是将所有查询算子按照一定的方法排序,每次执行一个算子,执行完后再执行下一个算子,称为物化策略。这种方法的缺点是需要将中间结果暂存,往往需要存到磁盘上,带来较大的开销。另一种策略是将多个算子同时执行,一个算子处理一条数据后,将数据传递给下一个算子,不需要存储中间结果,这种策略称为流水线策略。

我们考虑以下面这个关系代数表达式为例,描述物化策略和流水线策略的执行过程。

$$ \Pi_{grade}(\sigma_{id=2077010001}(student) \Join student_course) $$

查询计划树

  • 物化(Materialization)

如果采用物化策略,我们将从最底层的扫描算子开始,首先对 student 表进行扫描,筛选出 id=2077010001 的记录,扫描完成后将筛选出的记录暂存。随后将暂存下来的记录和 student_course 表中的记录输入连接算子 $\Join$,执行连接操作。连接操作完成后,将连接的结果物化下来,最后交给查询计划树根节点的投影算子 $\Pi_{grade}$,投影算子输出查询的最终结果。

物化策略的查询开销不仅仅是所有查询算子开销之和,当中间结果较大、超出内存大小时,必须将其物化到磁盘上,这一过程也会产生不小的开销。

  • 流水线(Pipelining)

物化策略的开销很大程度上来源于存储中间结果的过程,我们可以将关系代数树的多个算子组成一个流水线,每个算子的中间结果直接传递给流水线上的下一算子,从而避免存储中间结果的开销。

例如,$\Join$ 和 $\Pi_{grade}$ 算子可以组成流水线,每当连接算子产生一条结果时,马上就可以传给投影算子进行投影操作。通过结合连接和投影,避免中间结果的物化过程,直接产生最终结果。

流水线策略可以显著提高查询的执行效率,然而并不是所有算子都可以组成流水线。比如排序算子,在前一算子得到所有记录之前无法输出任何结果。

Authors: Congyuan Rao (4.76%), Wenbo Li (95.24%)