本文介绍 OceanBase 数据库处理大规模 DML 操作(INSERT/UPDATE/DELETE)的最佳实践,重点关注使用 PDML 的性能优化策略,以及数据库侧的配置建议。
PDML(Parallel Data Manipulation Language,并行数据操作语言)是 OceanBase 数据库提供的一种高性能数据处理技术,主要用于加速大规模数据的 INSERT、UPDATE 和 DELETE 操作。通过将数据操作任务分解并分配给多个并行执行单元,PDML 可以提高数据操作的吞吐量和效率。
PDML 工作原理
PDML 通过以下机制提高性能:
-
任务并行化:将大型 DML 操作分解为多个独立的子任务;
-
数据分区处理:针对分区表,每个分区可由不同执行线程并行处理;
-
资源优化利用:充分利用多核 CPU 和分布式计算资源。
PDML 适用场景
-
大批量数据操作(批处理作业)
-
数据仓库 ETL 过程
-
历史数据归档或清理
-
大规模数据初始化加载
PDML 开启方式
PDML 开启方式
OceanBase 数据库提供了四种开启 PDML 的方式:
-
SQL 语句 Hint 指定并行度 :通过在 SQL 语句中添加 Hint 来指定并行度。
DELETE /*+ enable_parallel_dml parallel(4) */ FROM table_name WHERE condition;UPDATE /*+ enable_parallel_dml parallel(8) */ table_name SET column_name = value WHERE condition;INSERT /*+ enable_parallel_dml parallel(6) */ INTO target_table SELECT * FROM source_table WHERE condition;
其中,enable_parallel_dml 用于启用 PDML,parallel(N) 用于指定并行度。
适用场景:适用于临时性的、对单条 SQL 语句的性能调优,不影响其他操作。例如,对某个特定查询或数据修改操作进行快速优化。
-
会话级设置并行度 :在会话级别设置并行度,影响当前会话中的所有后续 DML 操作。
SET _force_parallel_query_dop = 3;SET _force_parallel_dml_dop = 3;-- 此后的 DML 语句将自动应用并行处理DELETE FROM table_name WHERE column_name = 'EXPIRED';
Oracle 模式下:
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 3;ALTER SESSION FORCE PARALLEL DML PARALLEL 3;-- 此后的 DML 语句将自动应用并行处理DELETE FROM table_name WHERE column_name = 'EXPIRED';-- 关闭 session 级别的并行ALTER SESSION DISABLE PARALLEL QUERY;
适用场景: 适用于需要在单个会话中执行多个并行 DML 操作的批处理作业。例如,ETL 过程中,需要在同一个会话中执行多个数据转换和加载操作。
自动并行度(Auto DOP):启用自动并行度,让数据库根据系统资源和负载情况自动调整并行度。
/* 在 GLOBAL 级别启用 Auto DOP */SET global parallel_degree_policy = AUTO;/* 在 SESSION 级别启用 Auto DOP */SET session parallel_degree_policy = AUTO;SET parallel_degree_policy = AUTO;/* 使用 Hint 在查询级别启用 Auto DOP */SELECT /*+PARALLEL(AUTO)*/ * FROM ...;
适用场景: 适用于数据库自动优化并行度的场景,无需人工指定。例如,在资源充足的情况下,数据库可以自动增加并行度以提高查询速度。
-
表级并行度设置:在表创建或修改时指定默认并行度。
CREATE TABLE sales_history(id INT PRIMARY KEY,sale_date DATE,amount DECIMAL(10,2)) parallel 8;-- 或修改现有表ALTER TABLE customer_data parallel 6;
当您对指定了并行度的表执行 DML 操作且未显式禁用并行时,OceanBase 数据库会自动使用 PDML。
适用场景: 适用于经常需要批量处理的大表,可以长期提升 DML 性能。例如,对于一个经常需要进行数据清洗和转换的大型日志表,可以设置表级并行度以提高处理效率。
并行开启方式优先级由高到低的顺序如下:
表级并行 Hint 配置
全局并行 Hint 配置
SESSION 并行度
表并行度
案例:历史数据归档
某平台每天产生大量的订单数据,随着时间的推移,历史订单数据量越来越大,导致查询性能下降。为了提高查询效率,并降低存储成本,平台决定将超过一年的历史订单数据归档到历史表中。
面临的挑战
-
数据量巨大:每天需要归档的订单数据量达到数百万条。
-
时间窗口有限:归档操作需要在业务低峰期完成,时间窗口非常有限。
-
业务影响:归档过程不能对在线业务产生明显影响。
解决方案
使用 OceanBase 数据库的 PDML 技术,并行执行数据归档操作。
order_history,用于存储归档数据。
CREATE TABLE order_history LIKE orders;
ALTER TABLE orders parallel 8;
INSERT INTO ... SELECT 语句将历史数据从订单表迁移到历史表,并使用 DELETE 语句删除订单表中的历史数据。
INSERT /*+ enable_parallel_dml parallel(8) */ INTO order_historySELECT * FROM orders WHERE order_date < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);DELETE /*+ enable_parallel_dml parallel(8) */ FROM ordersWHERE order_date < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
PDML使用限制
V4.3.5
使用 BATCH 优化
-
场景:使用 BATCH DML(如 Multi queries 或 Array Binding)
-
原因:同时启用 PDML 和 BATCH DML 可能导致锁冲突和事务隔离性问题
不支持的 DML 语句类型
-
场景:仅支持 INSERT/DELETE/UPDATE/MERGE 操作
INSERT FROM SELECT
-
场景:INSERT 的值来自 SELECT 子句
主键/分区键自增列
-
场景:目标表包含主键自增列或分区键自增列 -
原因:PDML 无法保证自增列的单调性,因此不支持
IGNORE 关键字
-
场景:包含 IGNORE 子句的 DML 语句(如 INSERT IGNORE 或 DELETE IGNORE) -
原因:IGNORE 会忽略唯一冲突等错误,但 PDML 的并行处理可能导致数据一致性问题
多表操作
-
场景:涉及多表操作的 DML(如 JOIN 或子查询更新) -
原因:PDML 仅支持单表操作,多表操作需要分布式事务协调,复杂度较高
ON DUPLICATE KEY UPDATE
-
场景:INSERT 语句包含 ON DUPLICATE KEY UPDATE(即 INSERT_UP) -
条件:目标表存在唯一索引/全局索引,或更新主键/唯一键 -
原因:唯一冲突检测和更新需要原子性,PDML 的并行执行可能导致冲突检测不一致
语句显式禁用 PDML
-
场景:DML 语句通过优化器规则或转换逻辑被标记为禁用 PDML -
原因:某些优化规则(如触发器或外键约束)依赖串行执行逻辑
跨库操作
-
场景:DML 操作涉及跨数据库的 DBLink -
原因:跨库事务需要协调外部资源,PDML 的并行化可能引发一致性风险
嵌套 SQL
-
场景:DML 语句中包含外键约束或触发器 -
原因:外键约束和触发器的执行依赖于表之间的关联关系,PDML 的并行执行可能导致数据一致性问题
分区指定操作
-
场景:DELETE 语句通过 PARTITION 子句指定特定分区(如 DELETE FROM t1 PARTITION(p0)) -
原因:分区裁剪后的并行执行可能与 PDML 的分区调度策略冲突
非在线 DDL
-
非在线 DDL 操作期间的 DML(如创建索引或表结构变更) -
UPDATE 语句指定分区 -
修改 ON UPDATE CURRENT_TIMESTAMP 列 -
原因:PDML 可能干扰内部状态同步,并导致时间戳不一致
变量赋值
-
场景:包含变量赋值操作,并且变量赋值出现在子查询或嵌套语句中 -
原因:PDML 的并行执行要求语句必须是确定性的(无副作用)。变量赋值可能引入运行时状态依赖(如跨分片的变量修改),破坏并行执行的原子性和一致性
正交场景
-
外键约束 -
触发器 -
SQL 中包含 PL UDF 等
HINT 禁用
-
场景:通过 hint 禁用 PDML
V4.2.5
使用 BATCH 优化
-
场景:使用 BATCH DML(如 Multi queries 或 Array Binding) -
原因:同时启用 PDML 和 BATCH DML 可能导致锁冲突和事务隔离性问题
不支持的 DML 语句类型
-
场景:仅支持 INSERT/DELETE/UPDATE/MERGE 操作
INSERT FROM SELECT
-
场景:INSERT 的值来自 SELECT 子句
主键/分区键自增列
-
场景:目标表包含主键自增列或分区键自增列 -
原因:PDML 无法保证自增列的单调性,因此不支持
IGNORE 关键字
-
场景:包含 IGNORE 子句的 DML 语句(如 INSERT IGNORE 或 DELETE IGNORE) -
原因:IGNORE 会忽略唯一冲突等错误,但 PDML 的并行处理可能导致数据一致性问题
多表操作
-
场景:涉及多表操作的 DML(如 JOIN 或子查询更新) -
原因:PDML 仅支持单表操作,多表操作需要分布式事务协调,复杂度较高
ON DUPLICATE KEY UPDATE
-
场景:INSERT 语句包含 ON DUPLICATE KEY UPDATE(即 INSERT_UP) -
原因:唯一冲突检测和更新需要原子性,PDML 的并行执行可能导致冲突检测不一致
语句显式禁用 PDML
-
场景:DML 语句通过优化器规则或转换逻辑被标记为禁用 PDML -
原因:某些优化规则(如触发器或外键约束)依赖串行执行逻辑
跨库操作
-
场景:DML 操作涉及跨数据库的 DBLink -
原因:跨库事务需要协调外部资源,PDML 的并行化可能引发一致性风险
嵌套 SQL
-
场景:DML 语句中包含外键约束或触发器 -
原因:外键约束和触发器的执行依赖于表之间的关联关系,PDML 的并行执行可能导致数据一致性问题
分区指定操作
-
场景:DELETE 语句通过 PARTITION 子句指定特定分区(如 DELETE FROM t1 PARTITION(p0)) -
原因:分区裁剪后的并行执行可能与 PDML 的分区调度策略冲突
非在线 DDL
-
非在线 DDL 操作期间的 DML(如创建索引或表结构变更) -
UPDATE 语句指定分区 -
修改 ON UPDATE CURRENT_TIMESTAMP 列 -
原因:PDML 可能干扰内部状态同步,并导致时间戳不一致
变量赋值
-
场景:包含变量赋值操作,并且变量赋值出现在子查询或嵌套语句中 -
原因:PDML 的并行执行要求语句必须是确定性的(无副作用)。变量赋值可能引入运行时状态依赖(如跨分片的变量修改),破坏并行执行的原子性和一致性
正交场景
-
外键约束 -
触发器 -
SQL 中包含 PL UDF 等
HINT 禁用
-
场景:通过 hint 禁用 PDML

