首批通过分布式安全可靠测评,为关键业务系统打造
并行 DML
更新时间:2026-06-18 19:24:58
并行 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;
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| ========================================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------------------------- |
| |0 |OPTIMIZER STATS MERGE | |1 |18 | |
| |1 | PX COORDINATOR | |1 |18 | |
| |2 | EXCHANGE OUT DISTR |:EX10001 |1 |18 | |
| |3 | INSERT | |1 |17 | |
| |4 | EXCHANGE IN DISTR | |1 |4 | |
| |5 | EXCHANGE OUT DISTR (HASH)|:EX10000 |1 |4 | |
| |6 | OPTIMIZER STATS GATHER | |1 |4 | |
| |7 | SUBPLAN SCAN |ANONYMOUS_VIEW1|1 |4 | |
| |8 | PX BLOCK ITERATOR | |1 |4 | |
| |9 | TABLE SCAN |t3 |1 |4 | |
| ========================================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil), rowset=256 |
| 1 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil), rowset=256 |
| 2 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil), rowset=256 |
| dop=2 |
| 3 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil) |
| columns([{t1: ({t1: (t1.c1, t1.c2)})}]), partitions(p0), |
| column_values([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]) |
| 4 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil), rowset=256 |
| 5 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil), rowset=256 |
| (#keys=1, [column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)]), dop=2 |
| 6 - output([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.c1)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.c2)]), filter(nil), rowset=256 |
| 7 - output([ANONYMOUS_VIEW1.c1], [ANONYMOUS_VIEW1.c2]), filter(nil), rowset=256 |
| access([ANONYMOUS_VIEW1.c1], [ANONYMOUS_VIEW1.c2]) |
| 8 - output([t3.c1], [t3.c2]), filter(nil), rowset=256 |
| 9 - output([t3.c1], [t3.c2]), filter(nil), rowset=256 |
| access([t3.c1], [t3.c2]), partitions(p[0-3]) |
| is_index_back=false, is_global_index=false, |
| range_key([t3.c1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
34 rows in set
如果要禁用并行 DML,请在语句中插入如下 Hint:
/*+ DISABLE_PARALLEL_DML */
即使会话中启用了并行 DML,您也可以在指定 SQL 语句中使用 DISABLE_PARALLEL_DML Hint 禁用并行 DML。
在会话中启用和关闭并行 DML
默认情况下,即使 SQL语句中使用了 PARALLEL Hint,并行 DML 也是不开启的,所以还需要通过在会话上开启并行 DML。
在会话中启用并行 DML,MySQL 模式下语法为:
SET _FORCE_PARALLEL_DML_DOP = n;
其中 n 大于 1。
在会话中启用并行 DML,Oracle 模式下语法为:
ALTER SESSION ENABLE PARALLEL DML;
Oracle 模式下,如果需要在会话中强制开启并行 DML,请运行以下 SQL 语句:
ALTER SESSION FORCE PARALLEL DML PARALLEL n;
如下示例为,Oracle 模式下在会话中强制开启并行 DML。
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> ALTER SESSION FORCE PARALLEL DML PARALLEL 6;
Query OK, 0 rows affected
obclient> EXPLAIN INSERT INTO t2 SELECT * FROM t3;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ============================================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------------------------------ |
| |0 |OPTIMIZER STATS MERGE | |1 |16 | |
| |1 | PX COORDINATOR | |1 |16 | |
| |2 | EXCHANGE OUT DISTR |:EX10001 |1 |15 | |
| |3 | INSERT | |1 |15 | |
| |4 | EXCHANGE IN DISTR | |1 |2 | |
| |5 | EXCHANGE OUT DISTR (PKEY HASH)|:EX10000 |1 |2 | |
| |6 | OPTIMIZER STATS GATHER | |1 |2 | |
| |7 | SUBPLAN SCAN |ANONYMOUS_VIEW1|1 |2 | |
| |8 | PX BLOCK ITERATOR | |1 |2 | |
| |9 | TABLE SCAN |T3 |1 |2 | |
| ============================================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil), rowset=256 |
| 1 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| 2 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| dop=6 |
| 3 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil) |
| columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-2]), |
| column_values([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]) |
| 4 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)], [PARTITION_ID]), filter(nil), |
| rowset=256 |
| 5 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)], [PARTITION_ID]), filter(nil), |
| rowset=256 |
| (#keys=1, [column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)]), dop=6 |
| 6 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| 7 - output([ANONYMOUS_VIEW1.C1], [ANONYMOUS_VIEW1.C2]), filter(nil), rowset=256 |
| access([ANONYMOUS_VIEW1.C1], [ANONYMOUS_VIEW1.C2]) |
| 8 - output([T3.C1], [T3.C2]), filter(nil), rowset=256 |
| 9 - output([T3.C1], [T3.C2]), filter(nil), rowset=256 |
| access([T3.C1], [T3.C2]), partitions(p[0-3]) |
| is_index_back=false, is_global_index=false, |
| range_key([T3.C1]), range(MIN ; MAX)always true |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
36 rows in set
需要注意的是,在 SQL 语句中启用并行 DML 时,一般使用由 Hint 指定的并行度来执行查询,其优先级高于会话中强制指定的并行度。Oracle 模式下的示例如下:
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> ALTER SESSION FORCE PARALLEL DML PARALLEL 6;
Query OK, 0 rows affected
obclient> EXPLAIN INSERT /*+ PARALLEL(3) */ INTO t2 SELECT * FROM t3;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ============================================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------------------------------ |
| |0 |OPTIMIZER STATS MERGE | |1 |17 | |
| |1 | PX COORDINATOR | |1 |17 | |
| |2 | EXCHANGE OUT DISTR |:EX10001 |1 |17 | |
| |3 | INSERT | |1 |16 | |
| |4 | EXCHANGE IN DISTR | |1 |3 | |
| |5 | EXCHANGE OUT DISTR (PKEY HASH)|:EX10000 |1 |3 | |
| |6 | OPTIMIZER STATS GATHER | |1 |3 | |
| |7 | SUBPLAN SCAN |ANONYMOUS_VIEW1|1 |3 | |
| |8 | PX BLOCK ITERATOR | |1 |3 | |
| |9 | TABLE SCAN |T3 |1 |3 | |
| ============================================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil), rowset=256 |
| 1 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| 2 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| dop=3 |
| 3 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil) |
| columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-2]), |
| column_values([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]) |
| 4 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)], [PARTITION_ID]), filter(nil), |
| rowset=256 |
| 5 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)], [PARTITION_ID]), filter(nil), |
| rowset=256 |
| (#keys=1, [column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)]), dop=3 |
| 6 - output([column_conv(NUMBER,PS:(-1,0),NOT NULL,ANONYMOUS_VIEW1.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.C2)]), filter(nil), rowset=256 |
| 7 - output([ANONYMOUS_VIEW1.C1], [ANONYMOUS_VIEW1.C2]), filter(nil), rowset=256 |
| access([ANONYMOUS_VIEW1.C1], [ANONYMOUS_VIEW1.C2]) |
| 8 - output([T3.C1], [T3.C2]), filter(nil), rowset=256 |
| 9 - output([T3.C1], [T3.C2]), filter(nil), rowset=256 |
| access([T3.C1], [T3.C2]), partitions(p[0-3]) |
| is_index_back=false, is_global_index=false, |
| range_key([T3.C1]), range(MIN ; MAX)always true |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
36 rows in set
如果要禁用并行 DML,MySQL 模式下的 SQL 语句为:
SET _FORCE_PARALLEL_DML_DOP = 1;
如果要禁用并行 DML,Oracle 模式下的 SQL 语句为:
ALTER SESSION DISABLE PARALLEL DML;
禁用并行 DML 时,即使在 SQL 语句中使用 PARALLEL Hint,也不会执行并行 DML。 在会话中启用并行 DML 时,则并行执行对此会话中的所有 DML 语句都会生效。如果 SQL 语句通过 ENABLE_PARALLEL_DML Hint 启用并行 DML 时,则并行执行仅对指定语句生效。但是,如果没有具有并行属性的表,或者违反了并行操作的限制,即使启用了并行 DML,DML 操作仍然会串行执行。
支持分区间并行处理
将根据以下 SQL 语句进行展示说明表分区并行处理功能。
创建测试表
branch_sp_tbl_src。CREATE TABLE branch_sp_tbl_src(id INT PRIMARY KEY, v INT) PARTITION BY KEY(id) PARTITIONS 4;创建测试表
branch_sp_tbl_dest。CREATE TABLE branch_sp_tbl_dest LIKE branch_sp_tbl_src;查看执行计划。
执行下面 SQL 语句,将展示如何执行该插入操作。
obclient [test]> EXPLAIN BASIC INSERT /*+enable_parallel_dml parallel(100) query_timeout(1000000000)*/ INTO branch_sp_tbl_dest SELECT id, v FROM branch_sp_tbl_src ON DUPLICATE KEY UPDATE v = v + 1;返回结果如下:
+-------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------------------------------------------------------+ | ================================================ | | |ID|OPERATOR |NAME | | | ------------------------------------------------ | | |0 |PX COORDINATOR | | | | |1 |└─EXCHANGE OUT DISTR |:EX10000 | | | |2 | └─PX PARTITION ITERATOR| | | | |3 | └─INSERT_UP | | | | |4 | └─SUBPLAN SCAN |ANONYMOUS_VIEW1 | | | |5 | └─TABLE FULL SCAN|branch_sp_tbl_src| | | ================================================ | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil), rowset=16 | | 1 - output(nil), filter(nil), rowset=16 | | dop=100 | | 2 - output(nil), filter(nil), rowset=16 | | partition wise, force partition granule | | 3 - output(nil), filter(nil) | | columns([{branch_sp_tbl_dest: ({branch_sp_tbl_dest: (branch_sp_tbl_dest.id, branch_sp_tbl_dest.v)})}]), partitions(p[0-3]), | | column_values([column_conv(INT,PS:(11,0),NOT NULL,ANONYMOUS_VIEW1.id)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.v)]), | | update([branch_sp_tbl_dest.v=column_conv(INT,PS:(11,0),NULL,cast(branch_sp_tbl_dest.v + 1, INT(-1, 0)))]) | | 4 - output([ANONYMOUS_VIEW1.id], [ANONYMOUS_VIEW1.v]), filter(nil), rowset=16 | | access([ANONYMOUS_VIEW1.id], [ANONYMOUS_VIEW1.v]) | | 5 - output([branch_sp_tbl_src.id], [branch_sp_tbl_src.v]), filter(nil), rowset=16 | | access([branch_sp_tbl_src.id], [branch_sp_tbl_src.v]), partitions(p[0-3]) | | is_index_back=false, is_global_index=false, | | range_key([branch_sp_tbl_src.id]), range(MIN ; MAX)always true | +-------------------------------------------------------------------------------------------------------------------------------------+ 27 rows in set查询计划中算子分析如下:
- 0 号算子:表示这是一个并行执行协调器,它负责管理并行执行的进程。
- 1 号算子:表示数据将在不同的执行节点之间进行分发。
- 2 号算子:表示查询会遍历分区,这里 “partition wise” 意味着查询会智能地处理各个分区之间的数据。
- 3 号算子:表示插入或更新操作。如果插入的键在表中不存在,它将执行插入操作;如果存在,则执行更新操作。
- 4 和 5 号算子:表示对名为
branch_sp_tbl_src的表进行全表扫描。这个表是数据源,从中选择数据来进行插入操作。
使用说明
OceanBase 数据库支持如下 SQL 语句的并行执行能力:
INSERT INTO SELECTUPDATEDELETE
如果表上存在下列索引类型,则需要支持并行执行:
- 局部索引
- 单分区全局索引
- 多分区全局索引
并行 DML 支持的场景
| 场景 | INSERT | UPDATE | DELETE | MERGE INTO |
|---|---|---|---|---|
表上存在外键/TRIGGER(触发器)/PL UDF(用户自定义函数)/唯一索引
说明不能明确是否会触发触发器:当触发器与 DML 操作无关时,不会触发触发器时,会继续走并行 DML。例如,在 |
不支持 | 不支持 | 不支持 | 不支持 |
| 多表 DML | INSERT ALL 语法,不支持并行 DML |
支持关联 UPDATE 并行。 |
同 UPDATE | 语法不支持 |
| 自增列 | 部分场景支持并行 DML,详细介绍可参见下文示例。 | 支持 | 支持 | 支持(seq) |
| ArrayBinding batch 优化 | 不支持 | 不支持 | 不支持 | 不支持 |
| 使用 USER_VARIABLE | 不支持 | 不支持 | 不支持 | 不支持 |
| IGNORE | 不支持 | 不支持 | 不支持 | 语法不支持 |
| DBLink | 不支持 | 不支持 | 不支持 | 不支持 |
| 其他 | 以下语句不支持并行 DML:
|
包含 ON UPDATE CURRENT_TIMESTAMP 列不支持 |
INSERT 的写入表有自增列时,假如自增列是主键或者分区键时,并且该列被指定时不支持并行 DML。
示例如下:
创建表
tbl1,其中列col1为自增列并指定为主键。CREATE TABLE tbl1(col1 INT AUTO_INCREMENT PRIMARY KEY, col2 INT, col3 INT);创建表
tbl2,其中列col1为自增列。CREATE TABLE tbl1(col1 INT AUTO_INCREMENT, col2 INT, col3 INT);创建表
tbl3。CREATE TABLE tbl3(col1 INT, col2 INT, col3 INT);INSERT的写入数据时,因为自增列col1是主键,所以不支持并行 DML。INSERT /*+enable_parallel_dml parallel(3)*/ INTO tbl1 SELECT * FROM tbl3;INSERT的写入数据时,因为未指定列col1,所以支持并行 DML。INSERT /*+enable_parallel_dml parallel(3)*/ INTO tbl1(col2, col3) SELECT col2, col3 FROM tbl3;INSERT的写入数据时,因为列col1只是自增列,所以支持并行 DML。INSERT /*+enable_parallel_dml parallel(3)*/ INTO tbl2 SELECT * FROM tbl3;
并行 DML 关联更新
关联更新指在 UPDATE 语句中使用多表连接操作,基于关联表的数据更新目标表。通过并行 DML 功能,可以显著提升大规模数据更新操作的性能。
示例如下:
以下步骤展示了如何使用并行 DML 实现关联更新功能。
创建两个测试表
customers和orders。CREATE TABLE customers ( id INT PRIMARY KEY, name VARCHAR(50), customer_level VARCHAR(10) );CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, discount DECIMAL(3, 2), amount DECIMAL(10, 2) );插入测试数据。
向
customers表插入客户数据:INSERT INTO customers (id, name, customer_level) VALUES (1, 'Alice', 'VIP'), (2, 'Bob', 'NORMAL'), (3, 'Charlie', 'OTHER');向
orders表插入订单数据:INSERT INTO orders (order_id, customer_id, discount, amount) VALUES (101, 1, NULL, 1000.00), (102, 2, NULL, 2000.00), (103, 3, NULL, 1500.00), (104, 1, NULL, 3000.00), (105, 2, NULL, 2500.00);
并行 DML 关联更新。
通过
EXPLAIN查看并行 DML 关联更新的执行计划:通过PARALLELHint 指定并行度为 4,根据customers表中的客户等级(customer_level),更新orders表中的折扣字段(discount)。EXPLAIN UPDATE /*+ PARALLEL(4) */ orders o JOIN customers c ON o.customer_id = c.id SET o.discount = CASE WHEN c.customer_level = 'VIP' THEN 0.9 WHEN c.customer_level = 'NORMAL' THEN 0.95 ELSE 1.0 END;返回结果如下:
+------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ========================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | -------------------------------------------------------------------------- | | |0 |DISTRIBUTED UPDATE | |3 |50 | | | |1 |└─PX COORDINATOR | |3 |3 | | | |2 | └─EXCHANGE OUT DISTR |:EX10001|3 |3 | | | |3 | └─SHARED HASH JOIN | |3 |3 | | | |4 | ├─EXCHANGE IN DISTR | |3 |2 | | | |5 | │ └─EXCHANGE OUT DISTR (BC2HOST)|:EX10000|3 |2 | | | |6 | │ └─PX BLOCK ITERATOR | |3 |1 | | | |7 | │ └─TABLE FULL SCAN |c |3 |1 | | | |8 | └─PX BLOCK ITERATOR | |5 |1 | | | |9 | └─TABLE FULL SCAN |o |5 |1 | | | ========================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil) | | table_columns([{o: ({orders: (o.order_id, o.customer_id, o.discount, o.amount)})}]), | | update([o.discount=column_conv(DECIMAL_INT,PS:(3,2),NULL,CASE WHEN c.customer_level = 'VIP' THEN cast(0.9, DECIMAL_INT(3, 2)) WHEN c.customer_level | | = 'NORMAL' THEN 0.95 ELSE cast(1.0, DECIMAL_INT(3, 2)) END)]) | | 1 - output([o.order_id], [o.customer_id], [o.discount], [o.amount], [c.customer_level]), filter(nil), rowset=16 | | 2 - output([o.order_id], [o.customer_id], [o.discount], [o.amount], [c.customer_level]), filter(nil), rowset=16 | | dop=4 | | 3 - output([o.order_id], [o.customer_id], [o.discount], [o.amount], [c.customer_level]), filter(nil), rowset=16 | | equal_conds([o.customer_id = c.id]), other_conds(nil) | | 4 - output([c.id], [c.customer_level]), filter(nil), rowset=16 | | 5 - output([c.id], [c.customer_level]), filter(nil), rowset=16 | | dop=4 | | 6 - output([c.id], [c.customer_level]), filter(nil), rowset=16 | | 7 - output([c.id], [c.customer_level]), filter(nil), rowset=16 | | access([c.id], [c.customer_level]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([c.id]), range(MIN ; MAX)always true | | 8 - output([o.order_id], [o.customer_id], [o.discount], [o.amount]), filter(nil), rowset=16 | | 9 - output([o.order_id], [o.customer_id], [o.discount], [o.amount]), filter(nil), rowset=16 | | access([o.order_id], [o.customer_id], [o.discount], [o.amount]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([o.order_id]), range(MIN ; MAX)always true | +------------------------------------------------------------------------------------------------------------------------------------------------------------+ 38 rows in set