SQL语句的转换过程
SQL语句 -》 抽象语法树 -》 逻辑算子树 -》 物理算子树(物理执行计划)
物理执行计划的stage划分
为什么要进行stage划分?
对于分布式/并行SQL的执行,会将物理执行计划划分为若干stage,一个stage会使用多个线程/计算节点并行的执行计算Task,每个计算任务的执行逻辑是相同的,但是基于不同的数据split。多个计算任务能够并行执行,必须要保证其之间是没有依赖的,即每个计算任务完全基于自己的数据split即可完成计算。
我们知道stage的划分是按照数据是否需要redistribution来决定。那数据为什么要redistribution呢?一般来说是数据记录需要和相同分区的其他数据记录进行交互,比如agg、join操作。如果数据redistribution之后还只是独立的进行转换处理,那么redistribution是没有意义的,且完全可以在不redistribution的情况下实现相同的效果。
那在物理执行计划逻辑中包含数据redistribution,如果不进行stage划分,是无法保证多个Task能够无依赖的并行计算,因为一个Task的执行可能需要其他Task对应的数据split中的记录,所以必须进行进行stage划分,不同的stage之间进行数据redistribution,保证下一个stage的Task计算时只需要依赖自己的数据split,对其他Task无依赖,则可以并行的执行。
分布式/并行SQL查询的执行模式
-
单机多线程(Postgres / MSSQL)
所有的stage同时调度执行,每个线程执行一个task,task之间的shuffle 只是逻辑上的,不需要真的做 IO。
-
分布式并行执行(presto、Greenplum)
所有的stage同时调度执行,所有task分配到不同的计算机节点当中。一般为纯内存执行,一旦某个Task失败,需要重试整个查询。
-
批处理执行(SparkSQL、presto)
stage依次调度,只有父stage的Task执行完毕之后,才调度子stage的Task。Worker 级 fail-over