并行 DML 通过使用并行执行机制来提高对大型数据库的表和索引执行插入、更新、删除等操作,以提高执行效率。对于决策支持系统 (DSS)的数据库,并行 DML 提供了查询和更新功能,是对并行查询功能的补充。对于 OLTP 数据库,并行 DML 操作可以加速批处理作业的运行。
开启和关闭并行 DML
OceanBase 数据库支持在 SQL 语句或会话中显式启用并行 DML。
在 SQL 语句中启用和关闭并行 DML
在 SQL 语句中启用并行 DML,请在语句中插入如下 Hint:
/*+ ENABLE_PARALLEL_DML PARALLEL(3) */
一般情况下,ENABLE_PARALLEL_DML Hint 和 PARALLEL Hint 必须配合使用才能开启并行 DML。不过,当目标表的 Schema 上指定了表级别的并行度时,仅需指定 ENABLE_PARALLEL_DML Hint。
如下示例为同时使用 ENABLE_PARALLEL_DML Hint 和 PARALLEL(n) 参数指定并行度 n,并且 n > 1,并行度 dop=2。
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT) NOPARALLEL;
CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT) PARALLEL 11 PARTITION BY HASH(c1) PARTITIONS 3;
CREATE TABLE t3 (c1 INT PRIMARY KEY, c2 INT) PARALLEL 10 PARTITION BY HASH(c1) PARTITIONS 4;
obclient> EXPLAIN INSERT /*+ ENABLE_PARALLEL_DML PARALLEL(2) */ INTO t1 SELECT * FROM T3\G
*************************** 1. row ***************************
==============================================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
--------------------------------------------------------------
|0 |PX COORDINATOR | |400000 |537675|
|1 | EXCHANGE OUT DISTR |:EX10001|400000 |537675|
|2 | INSERT | |400000 |537675|
|3 | EXCHANGE IN DISTR | |400000 |482466|
|4 | EXCHANGE OUT DISTR (RANDOM)|:EX10000|400000 |302612|
|5 | SUBPLAN SCAN |VIEW1 |400000 |302612|
|6 | PX BLOCK ITERATOR | |400000 |247403|
|7 | TABLE SCAN |T3 |400000 |247403|
==============================================================
Outputs & filters:
-------------------------------------
0 - output(nil), filter(nil)
1 - output(nil), filter(nil), dop=2
2 - output(nil), filter(nil),
columns([{T1: ({T1: (T1.C1, T1.C2)})}]), partitions(p0), conv_exprs([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)])
3 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)]), filter(nil)
4 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)]), filter(nil), dop=2
5 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)]), filter(nil),
access([VIEW1.C1], [VIEW1.C2])
6 - output([T3.C1], [T3.C2]), filter(nil)
7 - output([T3.C1], [T3.C2]), filter(nil),
access([T3.C1], [T3.C2]), partitions(p[0-3])
1 row in set
如果要禁用并行 DML,请在语句中插入如下 Hint:
/*+ DISABLE_PARALLEL_DML */
即使会话中启用了并行 DML,您也可以在指定 SQL语句中使用 DISABLE_PARALLEL_DML Hint 禁用并行PDML。
在会话中启用和关闭并行 DML
默认情况下,即使 SQL语句中使用了 PARALLEL Hint,并行 DML 也是不开启的,所以还需要通过在会话上开启并行 DML。在会话中启用并行 DML,请运行以下 SQL 语句:
set _force_parallel_dml_dop = 3
说明
当 _
force_parallel_dml_dop被修改为大于 1 时,当前 session 上的 DML 都会以大于 1 的并行度执行,当_force_parallel_query_dop被修改为 1 时,当前 session 上的 DML 则不开启并行执行。
如下示例为在会话中开启并行 DML。
CREATE TABLE t1 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) NOPARALLEL;
CREATE TABLE t2 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) PARALLEL 11 PARTITION BY HASH(C1) PARTITIONS 3;
CREATE TABLE t3 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) PARALLEL 10 PARTITION BY HASH(C1) PARTITIONS 4;
obclient> set _force_parallel_dml_dop = 6;
Query OK, 0 rows affected
obclient> EXPLAIN INSERT INTO t2 SELECT * FROM t3\G
*************************** 1. row ***************************
===================================================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
-------------------------------------------------------------------
|0 |PX COORDINATOR | |400000 |537675|
|1 | EXCHANGE OUT DISTR |:EX10001|400000 |537675|
|2 | INSERT | |400000 |537675|
|3 | EXCHANGE IN DISTR | |400000 |482466|
|4 | EXCHANGE OUT DISTR (PKEY RANDOM)|:EX10000|400000 |302612|
|5 | SUBPLAN SCAN |VIEW1 |400000 |302612|
|6 | PX BLOCK ITERATOR | |400000 |247403|
|7 | TABLE SCAN |T3 |400000 |247403|
===================================================================
Outputs & filters:
-------------------------------------
0 - output(nil), filter(nil)
1 - output(nil), filter(nil), dop=6
2 - output(nil), filter(nil),
columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-2]), conv_exprs([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)])
3 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)], [PARTITION_ID]), filter(nil)
4 - (#keys=1, [column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)]), output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)], [PARTITION_ID]), filter(nil), dop=6
5 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)]), filter(nil),
access([VIEW1.C1], [VIEW1.C2])
6 - output([T3.C1], [T3.C2]), filter(nil)
7 - output([T3.C1], [T3.C2]), filter(nil),
access([T3.C1], [T3.C2]), partitions(p[0-3])
1 row in set
需要注意的是,在 SQL 语句中启用并行 DML 时,一般使用由 Hint 指定的并行度来执行查询,其优先级高于会话中强制指定的并行度。示例如下:
CREATE TABLE t1 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) NOPARALLEL;
CREATE TABLE t2 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) PARALLEL 11 PARTITION BY HASH(C1) PARTITIONS 3;
CREATE TABLE t3 (C1 NUMBER(38) PRIMARY KEY, C2 NUMBER(38)) PARALLEL 10 PARTITION BY HASH(C1) PARTITIONS 4;
obclient> set _force_parallel_dml_dop = 6;
Query OK, 0 rows affected
obclient> EXPLAIN INSERT /*+ PARALLEL(3) */ INTO t2 SELECT * FROM t3\G
*************************** 1. row ***************************
===================================================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
-------------------------------------------------------------------
|0 |PX COORDINATOR | |400000 |537675|
|1 | EXCHANGE OUT DISTR |:EX10001|400000 |537675|
|2 | INSERT | |400000 |537675|
|3 | EXCHANGE IN DISTR | |400000 |482466|
|4 | EXCHANGE OUT DISTR (PKEY RANDOM)|:EX10000|400000 |302612|
|5 | SUBPLAN SCAN |VIEW1 |400000 |302612|
|6 | PX BLOCK ITERATOR | |400000 |247403|
|7 | TABLE SCAN |T3 |400000 |247403|
===================================================================
Outputs & filters:
-------------------------------------
0 - output(nil), filter(nil)
1 - output(nil), filter(nil), dop=3
2 - output(nil), filter(nil),
columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-2]), conv_exprs([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)])
3 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)], [PARTITION_ID]), filter(nil)
4 - (#keys=1, [column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)]), output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)], [PARTITION_ID]), filter(nil), dop=3
5 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(NUMBER,PS:(38,0),NULL,VIEW1.C2)]), filter(nil),
access([VIEW1.C1], [VIEW1.C2])
6 - output([T3.C1], [T3.C2]), filter(nil)
7 - output([T3.C1], [T3.C2]), filter(nil),
access([T3.C1], [T3.C2]), partitions(p[0-3])
1 row in set
如果要禁用并行 DML,请运行以下 SQL 语句:
set _force_parallel_dml_dop = 1;
禁用并行 DML 时,即使在 SQL 语句中使用 PARALLEL Hint,也不会执行并行 DML。 在会话中启用并行 DML 时,则并行执行对此会话中的所有 DML 语句都会生效。如果 SQL 语句通过 ENABLE_PARALLEL_DML Hint 启用并行 DML 时,则并行执行仅对指定语句生效。但是,如果没有具有并行属性的表,或者违反了并行操作的限制,即使启用了并行 DML,DML 操作仍然会串行执行。
使用说明
OceanBase 数据库支持如下 SQL 语句的并行执行能力:
INSERT INTO SELECTUPDATEDELETE
如果表上存在下列索引类型,则需要支持并行执行:
- 局部索引
- 单分区全局索引
- 多分区全局索引
OceanBase 数据库不支持以下 SQL 语句使用并行 DML:
REPLACEMERGE INTOINSERT INTO ON DUPLICATE KEY UPDATE- 不支持多表 DML 语句
如果表上存在如下属性,也不支持并行 DML:
- 触发器
- 外键
CHECK约束- 唯一索引




