PARALLEL Hint 用于指定进行并行扫描(Parallel Scan)的表和并行度。
PARALLEL Hint 是一个三层级的 Hint:Global、Query Block、Table。每个级别都可以指定可选的并行度(integer),NO_PARALLEL 用于禁止并行。MySQL 标准 Hint 语法请参见 Optimizer Hints。级别 | 触发条件 | 行为 |
Global 级 | 在主查询中指定,且未给定 query block name 和 table name | integer 作为整个查询的默认并行度。子查询可通过自身的 PARALLEL Hint 覆盖该值。 |
Query Block 级 | 在非主查询中指定,或显式给定 query block name 但未给定 table name | integer 作为该子查询的默认并行度。 |
Table 级 | Hint 中给定了表名 | 若仅给表名而未给 integer,则向上继承(依次为 Query Block 级、Global 级、max_parallel_degree 变量)。若最终未取得并行度(即 max_parallel_degree 为0),则不并行。 |
NO_PARALLEL 时,该 Query Block 不会进入并行优化阶段。表级 Hint 仅影响当前表是否进行并行扫描;若 Query Block 和 Global 级未指定 Hint 且 max_parallel_degree 大于0,即使所有表都使用了 NO_PARALLEL,并行优化器仍会选择一个表进行并行扫描。max_parallel_degree 变量,并且不再检查 cost 和 table records 是否满足设置的阈值。-- Global 级别EXPLAIN SELECT /*+ PARALLEL(4) */ * FROM t1 WHERE a > 4;-- Query Block 级别(仅在最顶层查询起作用)EXPLAIN SELECT /*+ QB_NAME(q1) PARALLEL(@q1 4) */ * FROM t1 WHERE a > 4;-- Query Block 级别(仅在子查询中有效)EXPLAIN SELECT * FROM t3 WHERE a = (SELECT /*+ PARALLEL(2) */ COUNT(a) FROM t3);-- Table 级别EXPLAIN SELECT /*+ PARALLEL(t1 4) */ * FROM t1 WHERE a > 4;EXPLAIN SELECT /*+ PARALLEL(t3@q2 4) */ * FROM t3 WHERE a = (SELECT /*+ QB_NAME(q2) */ COUNT(a) FROM t3);EXPLAIN SELECT /*+ PARALLEL(@q2 t3 4) */ * FROM t3 WHERE a = (SELECT /*+ QB_NAME(q2) */ COUNT(a) FROM t3);
PARALLEL Hint 与固定查询计划结合,可以在不修改语句的情况下,对特定语句开启并行:CALL dbms_admin.statement_outline_add_rule('test', 'select /*+ PARALLEL(4) */ sum(c),b from t1 group by b');
PQ_DISTRIBUTE 用于指示并行查询优化器如何在查询计划中添加数据重分布操作,以及 GROUP BY、ORDER BY 和窗口函数(WINDOW)的并行执行策略。语法如下:
写法 | 含义 |
PQ_DISTRIBUTE(t1 NONE) | 单个 dist_type:控制本表分发。NONE = 不重分布(保持本地数据) |
PQ_DISTRIBUTE(t1 GATHER) | 单个 dist_type:控制本表分发。GATHER = 添加 collector(汇聚到 leader) |
PQ_DISTRIBUTE(t1 d1, d2) | 两个 dist_type:第一个 = 对端表(join 另一侧),第二个 = 本表。各取值同上 |
写法 | 含义 |
PQ_DISTRIBUTE(AGGREGATE GATHER) | 单阶段聚合:先将所有数据 gather 到 leader,再做聚合 |
PQ_DISTRIBUTE(AGGREGATE NONE) | 下推单阶段聚合:在各 worker 上直接聚合,不做数据重分布 |
PQ_DISTRIBUTE(AGGREGATE NONE, GATHER) | 两阶段聚合:worker 做局部聚合 → gather → leader 做最终聚合 |
PQ_DISTRIBUTE(SORT GATHER) | 不下推排序:先将所有数据 gather 到 leader,再做排序 |
PQ_DISTRIBUTE(SORT NONE, GATHER) | 下推排序:worker 做局部排序 → gather → leader 做归并排序 |
/*+ PQ_DISTRIBUTE([@query_block] target dist_type[, dist_type]) */
target 有三种类型:目标类型 | 语法形式 | 说明 |
表目标 | PQ_DISTRIBUTE([@qb] tbl_name dist_type[, dist_type]) | 控制表在 Join 中的数据分布方式 |
操作目标 | PQ_DISTRIBUTE([@qb] AGGREGATE|SORT dist_type[, dist_type]) | 控制聚合或排序操作的并行策略 |
命名窗口目标 | PQ_DISTRIBUTE([@qb] WINDOW win_name dist_type[, dist_type]) | 控制指定命名窗口函数的并行策略 |
@qb 为可选的 query block 名称(如 @qb1),用于指定 Hint 作用的查询块。dist_type 可选值为:NONE、GATHER。其中 HASH 和 BROADCAST 目前未生效,会被视为未指定。target 为表名时,Hint 控制该表在 Join 操作中的数据分布方式。写法 | 含义 |
PQ_DISTRIBUTE(t1 NONE) | 表 t1 不添加 Collector(数据留在各 Worker 上) |
PQ_DISTRIBUTE(t1 GATHER) | 表 t1 添加 Collector(数据汇聚到 Leader) |
PQ_DISTRIBUTE(t1 d1, d2) | d1 控制 Join 对端的分布方式,d2 控制本表(t1)的分布方式 |
dist_type 时,第一个参数 d1 作用于 Join 的对端表,第二个参数 d2 作用于本表。例如:-- t1 不添加 Collector(留在 Worker),Join 对端添加 Collector(汇聚到 Leader)SELECT /*+ PQ_DISTRIBUTE(t1 GATHER, NONE) */ * FROM t1 JOIN t2 ON t1.id = t2.id;
target 为 AGGREGATE 或 SORT 时,Hint 控制聚合或排序操作的并行执行策略。AGGREGATE)写法 | 含义 |
PQ_DISTRIBUTE(AGGREGATE GATHER) | 单阶段聚合:各 Worker 数据汇聚到 Leader 后执行聚合 |
PQ_DISTRIBUTE(AGGREGATE NONE) | 下推单阶段聚合:各 Worker 上直接执行完整聚合(无需重分布) |
PQ_DISTRIBUTE(AGGREGATE NONE, GATHER) | 两阶段聚合:各 Worker 先执行部分聚合,再汇聚到 Leader 执行最终聚合 |
-- 完全下推的一阶段聚合SELECT /*+ PQ_DISTRIBUTE(AGGREGATE NONE) */department, AVG(salary)FROM employeesGROUP BY department;-- Worker 和 Leader 二阶段聚合SELECT /*+ PQ_DISTRIBUTE(AGGREGATE NONE, GATHER) */department, AVG(salary)FROM employeesGROUP BY department;-- 只在 Leader 上执行的一阶段聚合SELECT /*+ PQ_DISTRIBUTE(AGGREGATE GATHER) */department, AVG(salary)FROM employeesGROUP BY department;
SORT)写法 | 含义 |
PQ_DISTRIBUTE(SORT GATHER) | 非下推排序:各 Worker 数据汇聚到 Leader 后执行排序 |
PQ_DISTRIBUTE(SORT NONE, GATHER) | 下推排序:各 Worker 先执行局部排序,再汇聚到 Leader 执行归并排序 |
-- Worker 局部排序 + Leader 归并排序SELECT /*+ PQ_DISTRIBUTE(SORT NONE, GATHER) */ *FROM large_tableORDER BY create_time DESC;-- 只在 Leader 上全局排序SELECT /*+ PQ_DISTRIBUTE(SORT GATHER) */ *FROM large_tableORDER BY create_time DESC;
target 为 WINDOW win_name 时,Hint 控制指定命名窗口函数的并行策略,语义与 SORT 类似。SELECT /*+ PQ_DISTRIBUTE(WINDOW w NONE, GATHER) */ SUM(val) OVER wFROM t1 WINDOW w AS (ORDER BY id);
-- 表目标:控制 t1 在 Join 中不添加 CollectorSELECT /*+ PQ_DISTRIBUTE(t1 NONE) */ * FROM t1 JOIN t2 ON t1.id = t2.id;-- 表目标(指定 query block):t1 添加 Collector,对端不添加SELECT /*+ PQ_DISTRIBUTE(@qb1 t1 NONE, GATHER) */ * FROM t1 JOIN t2 ON t1.id = t2.id;-- 操作目标:使用两阶段聚合SELECT /*+ PQ_DISTRIBUTE(AGGREGATE NONE, GATHER) */ dept, SUM(salary) FROM emp GROUP BY dept;-- 操作目标:下推排序SELECT /*+ PQ_DISTRIBUTE(SORT NONE, GATHER) */ * FROM t1 ORDER BY col1;-- 组合使用:同时指定表分布和聚合策略SELECT /*+ PQ_DISTRIBUTE(t1 NONE) PQ_DISTRIBUTE(AGGREGATE NONE, GATHER) */ dept, COUNT(*) FROM t1 GROUP BY dept;
HASH 和 BROADCAST 作为 dist_type 值目前暂不支持,使用时会被视为未指定(等同于不写该 Hint)。dist_type 用于表目标时,它控制本表的分布方式,JOIN 对端不受约束。dist_type 用于表目标时,第一个参数控制对端,第二个参数控制本表。PQ_DISTRIBUTE Hint 可在同一条 SQL 中组合使用,分别控制不同目标。-- 指定这个 IN 子查询使用 MATERIALIZATION 策略并且在并行计划不使用预先执行策略EXPLAIN FORMAT=TREESELECT * FROM t1WHERE t1.a IN (SELECT /*+ SUBQUERY(MATERIALIZATION, PQ_INLINE_EVALUATION) */ aFROM t2);-- 指定 Derived Table 子查询 t 使用预先执行策略EXPLAIN FORMAT=TREESELECT /*+ NO_MERGE(t) PQ_DISTRIBUTE(t1 NONE) */ t1.aFROM t1, (SELECT /*+ SUBQUERY(PQ_INLINE EVALUATION) */ aFROM t2) tWHERE t1.a = t.a;
文档反馈