暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

分布式数据库学习Note80:OceanBase社区版中,如何使优化器生成指定的执行计划?

Hint 机制可以使优化器生成指定的执行计划。

一般情况下,优化器会为用户查询选择最佳的执行计划,不需要用户使用 Hint 指定。但在某些场景下,优化器生成的执行计划可能不满足用户的要求,这时就需要用户使用 Hint 来指定生成某种执行计划。

Hint 语法

Hint 从语法上看是一种特殊的 SQL 注释,所不同的是在注释的左标记后("/*"符号)增加了一个"+"。 既然是注释,如果服务器端无法识别 SQL 语句中的 Hint,优化器会选择忽略用户 Hint 而使用默认的计划生成逻辑结构。另外,Hint 只影响优化器生成计划的逻辑结构,而不影响 SQL 语句的语义。

{ DELETE | INSERT | SELECT | UPDATE | REPLACE } /*+ [hint_text][,hint_text]... */

注意

如果使用 MySQL 的 C 客户端执行带 Hint 的 SQL 语句,需要使用 -c 选项登录,否则 MySQL 客户端会将 Hint 作为注释从用户 SQL 语句中去除,导致系统无法收到用户 Hint。

Hint 参数

Hint 相关参数名称、语义和语法如下表所示。

名称语法语义
NO_REWRITENO_REWRITE禁止 SQL 改写。
READ_CONSISTENCYREAD_CONSISTENCY (WEAK[STRONGFROZEN])读一致性设置(弱/强)。
INDEX_HINT/*+ INDEX(table_name index_name) */设置表索引。
QUERY_TIMEOUTQUERY_TIMEOUT(INTNUM)设置超时时间。
LOG_LEVELLOG_LEVEL([']log_level['])设置日志级别,当设置模块级别语句时候,以第一个单引号(')作为开始,第二个单引号(')作为结束;例如'DEBUG'。
LEADINGLEADING([qb_name] TBL_NAME_LIST)设置联接顺序。
ORDEREDORDERED设置按照 SQL 中的顺序进行联接。
FULLFULL([qb_name] TBL_NAME)设置表访问路径为主表等价于 INDEX(TBL_NAME PRIMARY)
USE_PLAN_CACHEUSE_PLAN_CACHE(NONE[DEFAULT])设置是否使用计划缓存:
  • NONE:表示不使用计划缓存。
  • DEFAULT:表示按照服务器本身的设置来决定是否使用计划缓存。
ACTIVATE_BURIED_POINTACTIVATE_BURIED_POINT(INTNUM, [FIX_MOD | BEFORE_MODE], INTNUM, [INTNUM | -INTNUM])用于调试,触发内部设定的错误点。
USE_MERGEUSE_MERGE([qb_name] TBL_NAME_LIST)设置指定表在作为右表时使用 Merge Join。
USE_HASHUSE_HASH([qb_name] TBL_NAME_LIST)设置指定表在作为右表时使用 Hash Join。
NO_USE_HASHNO_USE_HASH([qb_name] TBL_NAME_LIST)设置指定表在作为右表时不使用 Hash Join。
USE_NLUSE_NL([qb_name] TBL_NAME_LIST)设置指定表在作为右表时使用 Nested Loop Join。
USE_BNLUSE_BNL([qb_name] TBL_NAME_LIST)设置指定表在作为右表时使用 Block Nested Loop Join
USE_HASH_AGGREGATIONUSE_HASH_AGGREGATION([qb_name])设置聚合算法为 Hash。例如 Hash Group By 或者 Hash Distinct。
NO_USE_HASH_AGGREGATIONNO_USE_HASH_AGGREGATION([qb_name])设置 Aggregate 方法不使用 Hash Aggregate,使用 Merge Group By 或者 Merge Distinct。
USE_LATE_MATERIALIZATIONUSE_LATE_MATERIALIZATION设置使用晚期物化。
NO_USE_LATE_MATERIALIZATIONNO_USE_LATE_MATERIALIZATION设置不使用晚期物化。
TRACE_LOGTRACE_LOG设置收集 Trace 记录用于 SHOW TRACE 展示。
QB_NAMEQB_NAME( NAME )设置 Query Block 的名称。
PARALLELPARALLEL(INTNUM)设置分布式执行并行度。
TOPKTOPK(PRECISION MINIMUM_ROWS)设置模糊查询的精度和最小行数。 其中 PRECSION 为整型,取值范围[0,100],表示模糊查询的行数百分比;MINIMUM_ROWS 为最小返回行数。

说明

  • QB_NAME 语法是: @NAME
  • TBL_NAME 语法是: [db_name.]relation_name [qb_name]

QB_NAME 参数

在 DML 语句中,每一个 query_block 都会有一个 QB_NAME(Query Block Name),可以由用户指定,也可以由系统自动生成。在用户没有用 Hint 指定 QB_NAME 的时候,系统会按照 SEL$1SEL$2UPD$1DEL$1 方式从左到右(实际也是 Resolver 的解析顺序)依次生成。

通过 QB_NAME 可以精确定位到每一个表,也可以在某处指定任意 Query Block 的行为。TBL_NAME 中的 QB_NAME 用于定位表,在 Hint 中最前面的 QB_NAME 用于定位 Hint 作用于哪一个 query_block

如下例所示,按照默认规则,会为 SEL$1 中的 t1 表选择 t1_c1 路径,为 SEL$2 中的 t2 表选择主表(Primary)访问。

obclient> CREATE TABLE t1(c1 INT, c2 INT, KEY t1_c1(c1));
Query OK, 0 rows affected

obclient> CREATE TABLE t2(c1 INT, c2 INT, KEY t2_c1(c1));
Query OK, 0 rows affected

obclient> EXPLAIN SELECT * FROM t1, (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5);
 WHERE t1.c1 = 1\G
*************************** 1. row ***************************

Query Plan: 
=========================================================
|ID|OPERATOR                  |NAME     |EST. ROWS|COST |
---------------------------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN|         |4950     |28686|
|1 | TABLE SCAN               |t1(t1_c1)|990      |26669|
|2 | MATERIAL                 |         |5        |207  |
|3 |  SUBPLAN SCAN            |         |5        |207  |
|4 |   TABLE SCAN             |t2       |5        |207  |
=========================================================

Outputs & filters: 
-------------------------------------
  0 - output([t1.c1], [t1.c2], [.c1], [.c2]), filter(nil), 
      conds(nil), nl_params_(nil)
  1 - output([t1.c1], [t1.c2]), filter(nil), 
      access([t1.c1], [t1.c2]), partitions(p0)
  2 - output([.c1], [.c2]), filter(nil)
  3 - output([.c1], [.c2]), filter(nil), 
      access([.c1], [.c2])
  4 - output([t2.c1], [t2.c2]), filter([t2.c2 = 1]), 
      access([t2.c2], [t2.c1]), partitions(p0), 
      limit(5), offset(nil)

如果 SQL 通过 Hint 来指定 SEL$1 的 t1 表走主表,SEL$2 的 t2 表走索引,示例如下:

obclient> EXPLAIN SELECT /*+INDEX(t1 PRIMARY) INDEX(@SEL$2 t2 t2_c1)*/ * 
        FROM t1 , (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5)
        WHERE t1.c1 = 1\G
*************************** 1. row ***************************

Query Plan:
=========================================================
|ID|OPERATOR                  |NAME     |EST. ROWS|COST |
---------------------------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN|         |4950     |60030|
|1 | TABLE SCAN               |t1       |990      |40790|
|2 | MATERIAL                 |         |5        |17429|
|3 |  SUBPLAN SCAN            |         |5        |17429|
|4 |   TABLE SCAN             |t2(t2_c1)|5        |17429|
=========================================================

Outputs & filters: 
-------------------------------------
  0 - output([t1.c1], [t1.c2], [.c1], [.c2]), filter(nil), 
      conds(nil), nl_params_(nil)
  1 - output([t1.c1], [t1.c2]), filter([t1.c1 = 1]), 
      access([t1.c1], [t1.c2]), partitions(p0)
  2 - output([.c1], [.c2]), filter(nil)
  3 - output([.c1], [.c2]), filter(nil), 
      access([.c1], [.c2])
  4 - output([t2.c1], [t2.c2]), filter([t2.c2 = 1]), 
      access([t2.c2], [t2.c1]), partitions(p0), 
      limit(5), offset(nil)

说明

由于 INDEX(t1 PRIMARY) 本来就存在于 SEL$1,可以不用再指定 Hint 作用的 Query Block。

上述示例中 SQL 也可以写成如下方式:

SELECT /*+INDEX(t1 PRIMARY) INDEX(@SEL$2 t2@SEL$2 t2_c1)*/ * FROM t1 , (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5) WHERE t1.c1 = 1\G

<==>

SELECT /*+INDEX(t1 PRIMARY)*/ * FROM t1 , (SELECT /*+INDEX(t2 t2_c1)*/ * FROM t2 WHERE c2 = 1 LIMIT 5) WHERE t1.c1 = 1\G

<==>

SELECT /*+INDEX(@SEL$1 t1 PRIMARY) INDEX(@SEL$2 t2 t2_c1)*/ * FROM t1 , (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5) WHERE t1.c1 = 1\G

对于该 Hint,可以通过 EXPLAIN EXTENDED 命令的执行结果中的 Outline Data 来查看它的所有信息。

obclient> EXPLAIN EXTENDED SELECT * FROM t1, (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5)
 WHERE t1.c1 = 1\G
*************************** 1. row ***************************
Query Plan:
=========================================================
|ID|OPERATOR                  |NAME     |EST. ROWS|COST |
---------------------------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN|         |4950     |28686|
|1 | TABLE SCAN               |t1(t1_c1)|990      |26669|
|2 | MATERIAL                 |         |5        |207  |
|3 |  SUBPLAN SCAN            |         |5        |207  |
|4 |   TABLE SCAN             |t2       |5        |207  |
=========================================================
Used Hint:
-------------------------------------
  /*+
  */

Outline Data:
-------------------------------------
  /*+
      BEGIN_OUTLINE_DATA
      LEADING(@"SEL$1" ("test.t1"@"SEL$1" ""@"SEL$1" ))
      USE_NL(@"SEL$1" (""@"SEL$1" ))
      PQ_DISTRIBUTE(@"SEL$1" (""@"SEL$1" ) LOCAL LOCAL)
      USE_NL_MATERIALIZATION(@"SEL$1" (""@"SEL$1" ))
      INDEX(@"SEL$1" "test.t1"@"SEL$1" "t1_c1")
      FULL(@"SEL$2" "test.t2"@"SEL$2")
      END_OUTLINE_DATA
  */

Hint 使用规则

Hint 的一般使用规则如下:

  • 对于没有指定 Query Block 的 Hint 表明作用于本 Query Block。

    示例 1:由于t2 表在 Query Block2,并且无法通过改写提升到 Query Block1,所以 Hint 无法生效。

    obclient> EXPLAIN SELECT /*+INDEX(t2 t2_c1)*/ * 
            FROM t1 , (SELECT * FROM t2 WHERE c2 = 1 LIMIT 5)
            WHERE t1.c1 = 1\G
    *************************** 1. row ***************************
    
    Query Plan:
    =========================================================
    |ID|OPERATOR                  |NAME     |EST. ROWS|COST |
    ---------------------------------------------------------
    |0 |NESTED-LOOP JOIN CARTESIAN|         |4950     |28686|
    |1 | TABLE SCAN               |t1(t1_c1)|990      |26669|
    |2 | MATERIAL                 |         |5        |207  |
    |3 |  SUBPLAN SCAN            |         |5        |207  |
    |4 |   TABLE SCAN             |t2       |5        |207  |
    =========================================================
    
    
    Outputs & filters: 
    -------------------------------------
      0 - output([t1.c1], [t1.c2], [.c1], [.c2]), filter(nil), 
          conds(nil), nl_params_(nil)
      1 - output([t1.c1], [t1.c2]), filter(nil), 
          access([t1.c1], [t1.c2]), partitions(p0)
      2 - output([.c1], [.c2]), filter(nil)
      3 - output([.c1], [.c2]), filter(nil), 
          access([.c1], [.c2])
      4 - output([t2.c1], [t2.c2]), filter([t2.c2 = 1]), 
          access([t2.c2], [t2.c1]), partitions(p0), 
          limit(5), offset(nil)
    

    示例 2:SQL 可以通过改写将 t1 表提升到 SEL$1,则 Hint 生效。

    obclient> EXPLAIN SELECT /*+INDEX(t2 t2_c1)*/ * 
            FROM t1 , (SELECT * FROM t2 WHERE c2 = 1)
            WHERE t1.c1 = 1\G
    *************************** 1. row ***************************
    Query Plan:
    ==========================================================
    |ID|OPERATOR                  |NAME     |EST. ROWS|COST  |
    ----------------------------------------------------------
    |0 |NESTED-LOOP JOIN CARTESIAN|         |980100   |772448|
    |1 | TABLE SCAN               |t1(t1_c1)|990      |26669 |
    |2 | MATERIAL                 |         |990      |387237|
    |3 |  TABLE SCAN              |t2(t2_c1)|990      |387227|
    ==========================================================
    
    
    Outputs & filters: 
    -------------------------------------
      0 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil), 
          conds(nil), nl_params_(nil)
      1 - output([t1.c1], [t1.c2]), filter(nil), 
          access([t1.c1], [t1.c2]), partitions(p0)
      2 - output([t2.c1], [t2.c2]), filter(nil)
      3 - output([t2.c2], [t2.c1]), filter([t2.c2 = 1]), 
          access([t2.c2], [t2.c1]), partitions(p0)
    
  • 如果指定表行为,但在本 Query Block 中没有找到该表,或者发生冲突,那么 Hint 无效。

    对于没有找到表的情况可以参考第一条规则中的示例 1。如下示例为同时找到两个冲突的情况。

    obclient> EXPLAIN SELECT /*+INDEX(t1 PRIMARY)*/ * 
            FROM t1 , (SELECT * FROM t1 WHERE c1 = 1)
            WHERE t1.c1 = 1\G
    *************************** 1. row ***************************
    Query Plan:
    ==========================================================
    |ID|OPERATOR                  |NAME     |EST. ROWS|COST  |
    ----------------------------------------------------------
    |0 |NESTED-LOOP JOIN CARTESIAN|         |980100   |411890|
    |1 | TABLE SCAN               |t1(t1_c1)|990      |26669 |
    |2 | MATERIAL                 |         |990      |26679 |
    |3 |  TABLE SCAN              |t1(t1_c1)|990      |26669 |
    ==========================================================
    
    Outputs & filters: 
    -------------------------------------
      0 - output([t1.c1], [t1.c2], [t1.c1], [t1.c2]), filter(nil), 
          conds(nil), nl_params_(nil)
      1 - output([t1.c1], [t1.c2]), filter(nil), 
          access([t1.c1], [t1.c2]), partitions(p0)
      2 - output([t1.c1], [t1.c2]), filter(nil)
      3 - output([t1.c1], [t1.c2]), filter(nil), 
          access([t1.c1], [t1.c2]), partitions(p0)
    
  • 联接方法的 Hint 中指定的表如果找不到,则忽略该表,其他的指定依然生效;如果优化器不能生成指定的联接方法,就会选择其他方法,Hint 无效。

  • 联接顺序的 Hint 中如果存在表无法找到的情况,则该 Hint 完全失效。

常用 Hint 及语法

与其他数据库的行为相比,OceanBase 数据库优化器是动态规划的,已经考虑了所有可能的最优路径,Hint 主要作用是指定优化器的行为,并按照 Hint 执行 SQL 查询。

INDEX Hint

  • INDEX Hint 的语法如下:
table_name [[AS] alias] [index_hint_list]

index_hint_list:
index_hint [, index_hint] ...

index_hint:
USE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
  | IGNORE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
  | FORCE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)

index_list:
index_name [, index_name] ...

OceanBase 数据库中虽然支持指定多个 INDEX,但是对于 USE 和 FORCE 方式,只会用第一个 INDEX 生成 PATH,即使 SQL 语句中没有该 INDEX 的 filter 而导致全部扫描同时回表(即 OceanBase 数据库当前设计是认为写 Hint 的人比程序更明白那条路径是更好的)。IGNORE 类型会忽略所有指定的 INDEXUSEFORCE 方式和 Oracle 的Hint 方式实际是一样的,如果该方式的 INDEX 不存在或者处于 invalid 状态,则 Hint 无效。对于 IGNORE 方式,如果将包括主表在内的所有 INDEX 忽略,则 Hint 无效。

在 SQL 语句中,表名存在别名即 table_name [AS] alias ,必须写表别名,才能使 INDEX 生效。示例如下:

obclient> create table t1(c1 int, c2 int, c3 int);
Query OK, 0 rows affected

obclient> create index idx1 on t1(c1);
Query OK, 0 rows affected

obclient> create index idx2 on t1(c2);
Query OK, 0 rows affected

obclient> insert into t1 with recursive cte(n) as (select 1 from dual union all select n+1 from cte where n < 1000) select n, mod(n, 3), n from cte;
Query OK, 1 row affected

obclient> analyze table t1 COMPUTE STATISTICS for all columns size 128;
Query OK, 0 rows affected

obclient> explain select * from t1 where c1 = 1 and c2 = 1\G
*************************** 1. row ***************************
Query Plan: =======================================
|ID|OPERATOR  |NAME    |EST. ROWS|COST|
---------------------------------------
|0 |TABLE SCAN|T1(IDX1)|1        |5   |
=======================================

Outputs & filters: 
-------------------------------------
  0 - output([T1.C1], [T1.C2], [T1.C3]), filter([T1.C2 = 1]), rowset=256, 
      access([T1.__pk_increment], [T1.C1], [T1.C2], [T1.C3]), partitions(p0)

1 row in set

-------生效的 index
obclient> explain select /*+index(t idx2)*/ * from t1 t where c1 = 1 and c2 = 1\G
*************************** 1. row ***************************
Query Plan: ======================================
|ID|OPERATOR  |NAME   |EST. ROWS|COST|
--------------------------------------
|0 |TABLE SCAN|T(IDX2)|1        |5   |
======================================

Outputs & filters: 
-------------------------------------
  0 - output([T.C1], [T.C2], [T.C3]), filter([T.C1 = 1]), rowset=256, 
      access([T.__pk_increment], [T.C1], [T.C2], [T.C3]), partitions(p0)

1 row in set 

-------不生效的 index
obclient> explain select /*+index(t1 idx2)*/ * from t1 t where c1 = 1 and c2 = 1\G
*************************** 1. row ***************************
Query Plan: ======================================
|ID|OPERATOR  |NAME   |EST. ROWS|COST|
--------------------------------------
|0 |TABLE SCAN|T(IDX1)|1        |5   |
======================================

Outputs & filters: 
-------------------------------------
  0 - output([T.C1], [T.C2], [T.C3]), filter([T.C2 = 1]), rowset=256, 
      access([T.__pk_increment], [T.C1], [T.C2], [T.C3]), partitions(p0)

1 row in set 

根据示例结果,c1 = 1 过滤性优于 c2 = 1,INDEX Hint 不生效时使用优化器索引选择机制使用了 IDX1

FULL Hint

FULL Hint 的语法是用于指定表使用主表扫描,语法如下:

/*+ FULL(table_name)*/

FULL Hint 用于为指定表选择主表扫描,等价于 INDEX Hint /*+ INDEX(table_name PRIMARY)*/

ORDERED Hint

ORDERED Hint 可以指定按照 FROM 后面的表顺序作为联接顺序,语法如下:

 /*+ ORDERED */

如果指定该 Hint 后发生 SQL 改写,那么就按照改写后的 stmt 中 From Items 的顺序联接,因为改写时候 sub_query 会在 From Items 中对应位置填放新的 Table Item。

LEADING Hint

LEADING Hint 可以指定表的联接顺序,语法如下:

 /*+ LEADING(table_name_list)*/

在 table_name_list 中可以使用 () 表示内部各表的联接优先级,指定复杂联接。示例如下:

obclient> EXPLAIN BASIC SELECT /*+LEADING(d c b a)*/ * FROM t1 a, t1 b, t1 c, t1 d\G
*************************** 1. row ***************************
Query Plan:
======================================
|ID|OPERATOR                    |NAME|
--------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN  |    |
|1 | NESTED-LOOP JOIN CARTESIAN |    |
|2 |  NESTED-LOOP JOIN CARTESIAN|    |
|3 |   TABLE SCAN               |d   |
|4 |   MATERIAL                 |    |
|5 |    TABLE SCAN              |c   |
|6 |  MATERIAL                  |    |
|7 |   TABLE SCAN               |b   |
|8 | MATERIAL                   |    |
|9 |  TABLE SCAN                |a   |
======================================

obclient> EXPLAIN BASIC SELECT /*+LEADING((d c) (b a))*/ * FROM  t1 a, t1 b, t1 c, t1 d\G
*************************** 1. row ***************************
Query Plan:
======================================
|ID|OPERATOR                    |NAME|
--------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN  |    |
|1 | NESTED-LOOP JOIN CARTESIAN |    |
|2 |  TABLE SCAN                |d   |
|3 |  MATERIAL                  |    |
|4 |   TABLE SCAN               |c   |
|5 | MATERIAL                   |    |
|6 |  NESTED-LOOP JOIN CARTESIAN|    |
|7 |   TABLE SCAN               |b   |
|8 |   MATERIAL                 |    |
|9 |    TABLE SCAN              |a   |
======================================

obclient> EXPLAIN BASIC SELECT /*+LEADING((d c b) a))*/ * FROM t1 a, t1 b, t1 c, t1 d\G
*************************** 1. row ***************************
Query Plan:
======================================
|ID|OPERATOR                    |NAME|
--------------------------------------
|0 |NESTED-LOOP JOIN CARTESIAN  |    |
|1 | NESTED-LOOP JOIN CARTESIAN |    |
|2 |  NESTED-LOOP JOIN CARTESIAN|    |
|3 |   TABLE SCAN               |d   |
|4 |   MATERIAL                 |    |
|5 |    TABLE SCAN              |c   |
|6 |  MATERIAL                  |    |
|7 |   TABLE SCAN               |b   |
|8 | MATERIAL                   |    |
|9 |  TABLE SCAN                |a   |
======================================

为确保按照用户指定的顺序进行联接,LEADING Hint 的检查比较严格,如果发现 Hint 指定的 table_name 不存在,LEADING Hint 失效;如果发现 Hint 中存在重复表,LEADING Hint 失效。如果在 Optimizer 联接期间,按 table_id 无法在 From Items 中找到对应的表,则可能发生改写,那么该表及后面的表指定的 JOIN 顺序失效,该表前面的 JOIN 顺序依然有效。

USE_MERGE Hint

USE_MERGE可以指定表在联接时候使用 Merge Join 算法,将所指定的表作为右表。语法如下:

 /*+ USE_MERGE(table_name_list) */

注意

OceanBase 数据库中 Merge Join 必须有等值条件的 join-condition,因此无等值条件的两个表联接,use_merge 会无效。

关于 Merge Join 算法是否认为 A Merge Join B 等效于 B Merge Join A, 当前并没有最后结论。按照代价模型,Merge Join 计算代价时是区分左右表的,这也增加了 Hint 的灵活性,所以当前 Merge Join 区分左右表,即 use_merge 仅对表作为右表的时候生效。

USE_NL Hint

USE_NL指定表作为右表,在联接的时候使用 Nested Loop Join 算法,语法如下:

/*+ USE_NL(table_name_list) */

USE_HASH Hint

USE_HASH指定表作为右表,在联接的时候使用 Hash Join 算法,语法如下:

/*+ USE_HASH(table_name_list) */

PARALLEL Hint

PARALLEL 指定语句级别的并行度。语法如下:

/*+ PARALLEL(n) */

其中 n 为整数,表示并行度。

OceanBase 数据库也支持表级别的 PARALLEL Hint,语法如下:

/*+ PARALLEL(table_name n) */

如果同时指定了全局并行度和表级并行度,则表级并行度不会生效。示例如下:

obclient> CREATE TABLE tbl1 (col1 INT)  PARTITION BY HASH(col1) ;
Query OK, 0 rows affected 

obclient> EXPLAIN SELECT /*+ PARALLEL(3) PARALLEL(tbl1 5) */ * FROM tbl1\G
*************************** 1. row ***************************
Query Plan: ================================================
|ID|OPERATOR           |NAME    |EST. ROWS|COST|
------------------------------------------------
|0 |PX COORDINATOR     |        |1        |16  |
|1 | EXCHANGE OUT DISTR|:EX10000|1        |16  |
|2 |  PX BLOCK ITERATOR|        |1        |16  |
|3 |   TABLE SCAN      |TBL1    |1        |16  |
================================================

Outputs & filters:
-------------------------------------
  0 - output([INTERNAL_FUNCTION(TBL1.COL1)]), filter(nil)
  1 - output([INTERNAL_FUNCTION(TBL1.COL1)]), filter(nil), dop=3
  2 - output([TBL1.COL1]), filter(nil)
  3 - output([TBL1.COL1]), filter(nil),
      access([TBL1.COL1]), partitions(p0)

1 row in set 
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论