帮你快速理解、总结文档立即下载

并行查询概述

最近更新时间:2026-08-18 19:12:04
我的收藏

概述

TDSQL Boundless 并行查询是内建于计算引擎的并行查询框架。当查询数据量达到一定阈值时,优化器自动将查询计划分解为多个子任务,由多个 Worker 线程并行执行,使复杂查询的响应时间大幅下降。

总体流程

1. SQL 解析与优化:SQL 经过 MySQL 原生优化器生成串行执行计划
2. 并行计划生成:并行查询优化器对串行计划进行评估,判断是否满足并行条件
3. 计划分解:将符合条件的表扫描拆分为多个范围分片,生成 PartialPlan
4. 并行执行:Worker 线程(简称 Worker)各自执行 PartialPlan,独立扫描分配到的数据分片
5. 结果收集:Leader 线程(简称 Leader)通过 Collector 操作汇总各 Worker 的结果,必要时做归并排序或去重
6. 返回客户端:Leader 将最终结果返回客户端


适用场景

多表关联查询:JOIN 查询涉及大表扫描
聚合分析:GROUP BY + 聚合函数的大数据量查询
排序查询:需要对大量数据进行 ORDER BY 排序
分区表查询:按分区键并行扫描各分区
含子查询的复杂 SQL:子查询可并行预先执行

功能原理

并行计划生成

并行查询在 MySQL 原生优化器之后工作。MySQL 先产生串行执行计划,并行查询优化器再对该计划进行分析,决策过程与代价模型详见 并行查询优化器
并行计划生成的关键检查包括:
1. 参数限制检查max_parallel_workers 必须大于 0、max_parallel_degree 必须有效或存在 PARALLEL HINT,否则直接退出
2. 代价评估:检查串行执行代价是否超过 parallel_plan_cost_thresholdparallel_query_switchforce=on 或存在 PARALLEL HINT 时跳过此检查
3. 并行安全检查:遍历查询中所有表达式,任一表达式不支持并行执行则拒绝并行
4. 分布策略选择:为每张表选择分布类型(详见 并行查询优化器 中的分布模型章节)
5. JOIN 路径组合:对 outer/inner 两侧路径,剪枝不兼容组合,必要时插入 Collector 桥接
6. 最优路径选择:根据代价选择路径,优先选 HINT 匹配最多的路径;系统变量 parallel_plan_compare_serial_cost 控制串行路径是否参与比较
7. Slice 划分:沿最优路径在 Collector 处切分,根 Slice 运行于 Leader,每个子 Slice 对应一个 PartialPlan

Slice 与 PartialPlan

并行计划将原始计划按 Slice 进行分片。每个 Slice 是一个独立的执行单元:
Slice 0(Leader 端):在 Leader 上执行,负责汇总结果。包括 Collector 操作和需要全局视角的操作
Slice 1 ~ N(Worker 端):在 Worker 上并行执行,每个 Worker 可能包含并行扫描(支持多张表的并行扫描)
例如一个简单的 SELECT * FROM t1 WHERE a > 0 的并行计划:
Slice 1:4 个 Worker 各自扫描 t1 的 1/4 数据范围
Slice 0:Leader 通过 Collector 收集 4 个 Worker 的结果
对于带 JOIN 的查询 SELECT * FROM t1 JOIN t2
Slice 1:4 个 Worker 并行扫描 t1,各自与 t2 在本 Worker 内完成 Hash Join
Slice 0:Leader 通过 Collector 收集 4 个 Worker 的 JOIN 结果
说明:
常见场景为根 Slice 以及一层子 Slice 的两层结构,详见 并行查询优化器

并行扫描

并行查询支持两种并行扫描方式,优化器根据表结构和查询特征自动选择。可通过 PARALLEL HINT 显式指定扫描类型,详见 优化器 Hints

Dynamic Range Scan(动态范围并行扫描)

将表数据按主键范围动态切分为 N 个连续分片。每个 Worker 负责一个分片的扫描。
适用场景
未分区或无需按分区分片的普通表
带范围条件的查询(WHERE id BETWEEN X AND Y),优化器可进一步剪枝无关分片
工作方式
1. 优化器估算表的总行数和数据分布
2. 将 Key 空间均匀切分为 N 个区间(N 远大于系统变量 max_parallel_degree
3. 每个 Worker 从 N 个区间中动态争抢工作,防止数据倾斜

Partition Scan(分区并行扫描)

按物理分区将数据分片,每个分区分配给一个 Worker。
适用场景
使用 HASH 或 RANGE 分区的分区表
希望利用分区裁剪的查询,例如针对分区键的等值 JOIN(WHERE partition_key = X
工作方式
1. 优化器识别表中可用的分区列表
2. 将各分区均匀分配给 Worker
3. Worker 扫描分配给自己的分区
并行扫描方式选择
优化器决策:
分区表且分区数足够多(≥ 并行度),优先使用 Partition Scan
非分区表或分区数少,使用 Dynamic Range Scan
通过 HINT 显式指定:SELECT /*+ PARALLEL(t PARTITION) */SELECT /*+ PARALLEL(t DYNAMIC_RANGE) */,详细参考 优化器 Hints

Gather(结果收集)

Gather 是 Leader 线程从多个 Worker 收集结果的算子,它属于一种 Collector。它位于 Leader 端计划的关键位置,负责将并行执行的结果汇总。执行计划中 Gather 节点的具体输出格式详见 并行计划解读
Gather 支持多种数据处理模式:
模式
适用场景
说明
普通 Gather
无需保证顺序
简单将各 Worker 结果逐行收集并传递给上层算子
Merge Sort
需要 ORDER BY 输出
收集时对各 Worker 已排序的结果做归并排序。Worker 端做局部排序,Leader 端做归并
Gather 也支持对结果进行流式或物化输出(上层算子需要重复扫描时物化)。

并行聚合

GROUP BY 聚合操作在并行执行中有多种策略,优化器根据查询特征自动选择最优方案。

一阶段聚合

Worker 只负责扫描数据,数据汇聚到 Leader 后,由 Leader 执行聚合。
适用场景
聚合函数或 GROUP BY 表达式不满足下推条件(如带 DISTINCT 的聚合、不可两阶段的 GROUP_CONCAT / LISTAGG 等),无法将聚合下推到 Worker 时的兜底策略。

两阶段聚合(默认策略)

Worker 先执行局部聚合,接着 Gather 汇总, Leader 执行最终聚合。
流程
1. 各 Worker 并行扫描数据,对各自范围内的数据执行局部 GROUP BY
2. Worker 将局部聚合结果发送给 Leader
3. Leader 对来自所有 Worker 的中间结果再次执行 GROUP BY,得到最终聚合结果

完全下推聚合

当优化器可以确定各 Worker 间的 GROUP BY 键值不会重复时,将聚合完全下推到 Worker。此时 Leader 无需再次 GROUP BY,只需做简单汇总。
开启条件
parallel_query_switchfull_grouping_pushdown 选项已开启(默认开启)
聚合函数和 GROUP BY 表达式满足下推安全性
数据的分布与 GROUP BY 表达式兼容,每个 Worker 上的分组数据完整
对于 Partition Scan,需要分区键是 GROUP BY 列的前缀
对于 Dynamic Range Scan,需要表上的 Distinct Index 与 GROUP BY 列有公共前缀

并行排序

下推排序(默认)

Worker 先对各自结果执行排序,Leader 通过 Gather Merge Sort 归并:
1. 各 Worker 使用本地排序算法(filesort)对各自数据排序
2. Leader 启动 Merge Sort,同时从 N 个 Worker 的有序结果流中读取
3. 通过优先队列按 sortkey 升序归并,逐行返回
优势:充分利用多核并行排序能力,加速大数据量排序

非下推排序

当排序列无法下推(排序表达式包含非并行安全的函数、排序列是常量),数据先通过 Collector 到 Leader,再在 Leader 上串行排序。