首批通过分布式安全可靠测评,为关键业务系统打造
并行执行分类与优化
更新时间:2026-06-30 09:28:55
OceanBase 数据库提供了多种语句的并行执行支持,包括以下几个主要类别:
- 并行查询
- 并行 DML
- 并行 DDL
- 并行
LOAD DATA - 并发 DDL
并行查询
主要应用场景
SELECT语句及其子查询- DML 语句(
INSERT/UPDATE/DELETE)的查询部分 - 外表查询
决策过程
并行查询的执行决策涉及两个关键方面:
是否执行并行查询:
- 如果查询中使用了
PARALLELHint,会话开启了并行查询,或者TABLE属性指定了并行,将启用并行查询。
- 如果查询中使用了
确定并行度:
- 对于基表扫描或索引扫描 DFO,其并行度由
PARALLELHint、会话并行属性,或TABLE属性来决定。 - 如果运行时检测到某 DFO 访问的数据不足一个宏块,其运行时并行度会局部自动降低。
JOIN等中间节点的 DFO 并行度继承自JOIN左支子 DFO 的并行度。- 部分 DFO 不允许并行执行(例如计算
ROWNUM的节点),它们的并行度会被强制设为 1。
- 对于基表扫描或索引扫描 DFO,其并行度由
并行 DML
大多场景下,通过并行 DML(Parallel DML,简称 PDML)可以显著提升数据导入、更新和删除操作的性能。
DML 并行度
DML 的并行度与查询部分的并行度一致。启用并行 DML 时,查询部分将自动启用并行。读取的数据根据待更新表的分区位置进行重分布,然后由多个线程并行执行 DML,每个线程负责若干个分区。
当并行度与目标表的分区数存在倍数关系时,通常能达到最佳性能。当并行度大于分区数时,会有多个线程处理同一个分区的数据;当并行度小于分区数时,单个线程可能处理多个分区的数据,并且每个线程处理的分区不重合。
- 并行度大于目标表分区数时,建议并行度为分区数的整数倍。通常,同时向一个分区插入数据的线程数不应超过 4 个,因为超过这个值后扩展性受到限制,日志同步可能成为瓶颈,另外还有一些分区级别的锁同步开销。
- 并行度小于目标表分区数时,建议分区数是并行度的整数倍,以避免插入工作量不均衡的情况。
索引表处理策略
并行 DML 支持自动维护索引表。
- 对于本地索引,存储层会在并行 DML 更新主表时自动处理本地索引。
- 对于全局索引,使用并行 DML 框架时,会生成相应计划以维护全局索引。
下面是针对两个全局索引的处理流程:
- DFO1 首先负责主表的更新。
- DFO1 然后将全局索引 1 和全局索引 2 所需数据传递给 DFO2,DFO2 负责更新全局索引表 1。
- 最终,DFO2 将全局索引 2 所需数据传递给 DFO3,DFO3 完成全局索引表 2 的更新。

上述策略适用于所有 INSERT、DELETE、UPDATE 语句。对于 MERGE 语句,索引维护操作集中在一个 DFO 中处理,如下图所示:
- DFO1 首先负责主表的更新。
- DFO1 然后将全局索引 1 和全局索引 2 所需数据传递给 DFO2,DFO2 内部逐个完成全部全局索引的维护操作。

更新分区键的处理策略
对于 UPDATE 语句,当主表或全局索引表的分区键被更新时,需要执行 Row Movement 操作,即将旧数据从旧分区删除,然后将新数据插入新分区。在发生 Row Movement 时,将 UPDATE 操作分解为 DELETE 和 INSERT 两个步骤,即将涉及 Row Movement 的 UPDATE DFO 拆分为两个 DFO。第一个 DFO 负责 DELETE,第二个 DFO 负责 INSERT。为避免主键冲突,必须确保 DELETE DFO 完全执行完成后才能开始执行 INSERT DFO。
事务处理
OceanBase 数据库并行 DML 和普通 DML 语句一样,完全支持事务处理。并行 DML 语句可以和其它查询语句一起出现在同一个事务中,执行完成并行 DML 语句后无需立即提交事务,就可以在后继的查询语句中读取到 DML 语句的结果。
在 OceanBase 数据库 V4.1.0 之前版本,当并行 DML 执行时间超长时,需要给租户配置项 undo_retention 设置合适的值,否则可能发生 -4138 (OB_SNAPSHOT_DISCARDED) 错误,导致 SQL 在内部反复重试,直至超时。
undo_retention字面意思是 Undo 的保留位点,即从当前时间回溯多长时间的 Undo 日志是保留下来的。对于 OceanBase 数据库来说,是将该时段的所有数据多版本保留下来。当并行 DML 执行时间超过undo_retention设定的时间时,多版本数据可能被淘汰,当 DML 中的任何后继操作试图访问淘汰的多版本数据时,就会触发OB_SNAPSHOT_DISCARDED报错。undo_retention的默认值是 30 分钟,这意味着在默认情况下,如果并行 DML 语句 30 分钟内不能执行完成,无论语句的超时时间设定为多少,语句都可能执行超时并报错。一般来说,如果业务中的最长并行 DML 的执行时间为 2h 时,undo_retention可以设置为 2.5h。undo_retention不能随意设置为极大值,那会导致多版本数据无法回收,磁盘爆盘。
从 OceanBase 数据库 V4.1.0 版本起,并行 DML 的执行不再依赖 undo_retention 设定。多版本数据会根据事务版本号回收,只要事务还活跃,事务对应的版本号能读到的内容就不会回收。不过,数据盘满的场景是例外,此时还是会强行回收多版本数据,并行 DML 会收到 OB_SNAPSHOT_DISCARDED 报错,并自动重试整个 SQL。
旁路导入
在内存空间不足的情况下,由于并行 DML 容易报告内存不足错误,未经旁路导入路径的并行 DML 会先将数据写入 MemTable,然后通过转储和合并的方式写入磁盘。由于并行 DML 将数据快速写入 MemTable,当写入速度超过转储速度时,内存将不断增长,最终导致内存不足错误。
为解决这一问题,OceanBase 数据库的存储层引入了旁路导入功能。当并行 DML 使用旁路导入功能执行 INSERT 语句时,数据将直接绕过 MemTable 写入磁盘,既避免了内存不足问题,又提高了数据导入性能。
用户可以通过 APPEND Hint 开启旁路导入功能。在开始旁路导入之前,要求提交上一个事务并设置 AUTOCOMMIT = 1。在 OceanBase 数据库 V4.2.0 版本中,旁路导入功能必须与并行 DML 配合使用,如果未通过提示或会话开启并行 DML,则旁路导入的提示将被自动忽略。以下是语法示例:
SET AUTOCOMMIT = 1;
INSERT /*+ APPEND ENABLE_PARALLEL_DML PARALLEL(3) */ INTO t1 SELECT * FROM t2;
无法并行的 DML 操作
为确保正确的 DML 语义,下列场景中的查询部分可并行,但 DML 部分无法并行:
- 如果目标表包含
LOCAL UNIQUE INDEX,则 DML 部分不可并行,而查询部分仍可并行。 INSERT ON DUPLICATE KEY UPDATE语句的 DML 部分不可并行。- 如果目标表包含触发器、外键,则 DML 部分不可并行。
- 如果 DML 启用了
IGNORE模式,则 DML 部分不可并行。 - 多表的
INSERT ALL、UPDATE、DELETE、MERGE INTO语句不可并行。 - ArrayBinding batch 的优化不支持并行。
- DBLink 不支持并行。
INSERT...VALUES...、INSERT UPDATE或REPLACE语句不支持并行。- 包含
ON UPDATE CURRENT_TIMESTAMP的列不支持并行。
如果发现 DML 未并行执行,可通过 EXPLAIN EXTENDED 命令查看 Note 字段,以确定未并行执行的原因。
Row Movement 操作
在更新分区表的分区键时,可能会导致数据从一个分区搬迁到另一个分区。在 Oracle模式下,可以通过以下命令禁止数据跨分区搬迁:
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT) PARTITION BY HASH(c1) PARTITIONS 3;
ALTER TABLE t1 DISABLE ROW MOVEMENT;
obclient> UPDATE t1 SET c1 = c1 + 100000000;
OBE-14402: updating partition key column would cause a partition change
然而,并行 DML 会忽略表的 ROW MOVEMENT 属性,始终允许更新分区键。
并行 DDL
所有的并行 DDL 操作都通过特定的 Parallel DML 完成。例如,创建索引本质上是创建一个索引空表,然后并行地从主表查询出索引列数据,最后并行地插入到索引表中。OceanBase 数据库支持并行执行的 DDL 语句包括:
CREATE TABLE AS SELECTALTER TABLECREATE INDEX
通过 HINT 指定并行度
CREATE INDEX 语句支持通过 PARALLEL Hint 开启并行,其余 DDL 都只支持 Session 变量和 TABLE PARALLEL 属性来开启。
语法如下:
CREATE /*+ PARALLEL(3) */ INDEX IDX ON t1(c2);
通过 SESSION 变量指定并行度
上述所有 DDL 语句都支持通过 Session 变量来指定并行度。指定并行度后,该 Session 上的所有 DDL 都自动按照该并行度并行执行,并且查询部分和修改部分都使用相同的并行度。
在 Oracle 模式下,使用
ALTER SESSION修改并行度,语法示例如下:-- 并行创建索引 ALTER SESSION FORCE PARALLEL DDL PARALLEL 3; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT); CREATE INDEX IDX ON t1(c2);在 OceanBase 数据库 V4.2.0 版本中,Oracle 模式下
CREATE TABLE AS SELECT开启并行,使用的是ALTER SESSION FORCE PARALLEL DML PARALLEL,而非ALTER SESSION FORCE PARALLEL DDL PARALLEL。-- 并行 CTAS 建表 ALTER SESSION FORCE PARALLEL DML PARALLEL 3; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT); CREATE TABLE t2 AS SELECT * FROM t1;在 MySQL 模式下,语法稍有不同,会使用
SET语句设定 Session 变量来控制并行度。示例如下:-- 并行创建索引 SET _FORCE_PARALLEL_DDL_DOP = 3; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT); CREATE INDEX IDX ON t1(c2);在 OceanBase 数据库 V4.2.0 版本中,MySQL 模式下
CREATE TABLE AS SELECT开启并行,使用的是SET _FORCE_PARALLEL_DML_DOP,而非SET _FORCE_PARALLEL_DDL_DOP。-- 并行 CTAS 建表 SET _FORCE_PARALLEL_DML_DOP = 3; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT); CREATE TABLE t2 AS SELECT * FROM t1;
通过表 PARALLEL 属性指定并行度
当 DDL 相关表上有 PARALLEL 属性时,可以用下面的方法开启并行 DDL。
在 Oracle 模式下,使用
ALTER SESSION命令开启并行,语法如下:-- 并行创建索引 ALTER SESSION ENABLE PARALLEL DDL; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT) PARALLEL = 3; CREATE INDEX IDX ON t1(c2) PARALLEL = 2;在 OceanBase 数据库 V4.2.0 版本中,Oracle 模式下
CREATE TABLE AS SELECT开启并行,使用的是ALTER SESSION FORCE PARALLEL DML PARALLEL,而非ALTER SESSION FORCE PARALLEL DDL PARALLEL。-- 并行 CTAS 建表 ALTER SESSION ENABLE PARALLEL DML; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT) PARALLEL = 3; CREATE TABLE t2 PARALLEL 2 AS SELECT * FROM t1;在 MySQL 模式下,使用
SET语句设定 Session 变量来开启并行执行。示例如下:-- 并行创建索引 SET _ENABLE_PARALLEL_DDL = 1; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT) PARALLEL = 3; CREATE INDEX IDX ON t1(c2) PARALLEL = 2;在 OceanBase 数据库 V4.2.0 版本中,MySQL 模式下
CREATE TABLE AS SELECT开启并行,使用的是SET _ENABLE_PARALLEL_DML,而非SET _ENABLE_PARALLEL_DDL。-- 并行 CTAS 建表 SET _ENABLE_PARALLEL_DML = 1; CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, c4 INT) PARALLEL = 3; CREATE TABLE t2 PARALLEL 2 AS SELECT * FROM t1;
如果同时指定了 PARALLEL Hint、FORCE SESSION PARALLEL、表级 PARALLEL 属性中的两个或多个,那么它们的优先级如下: PARALLEL Hint 优先级 > FORCE SESSION PARALLEL 优先级 > 表 PARALLEL 属性优先级
CREATE INDEX 语句无论是否开启并行,总是会走旁路导入(Direct Write,Bypass memtable)。
注意
`CREATE TABLE AS SELECT` 语句目前(OceanBase 数据库 V4.2.0 版本)还不支持旁路导入功能,如果数据量比较大,建议先建立空表,然后使用并行 DML 旁路导入模式并行插入。
并行 LOAD DATA
LOAD DATA 的实现不是基于并行 DML,它的实现方式是:先用多个线程并行切分 csv 文件,拼成多个 INSERT 语句,然后用一定的并行度分发执行这些 INSERT 语句。
LOAD DATA /*+ parallel(2) */ infile "test.csv" INTO TABLE t1 FIELDS TERMINATED BY ',' ENCLOSED BY '"';
上述语句中,PARALLEL 选项指定加载数据的并行度,如果没有指定 PARALLEL Hint,则默认以 PARALLEL 为 4 来并行执行 LOAD DATA。PARALLEL 建议取值范围是 0 到 租户的最大 CPU 数。
并发 DDL
并行 DDL 与并发 DDL 对比
上文章节中所述的并行 DDL 的概念是指单条 DDL 操作通过使用多线程来加快执行速度,而这些操作依然是串行地处理。换句话来说,多线程可以在单一操作内并行工作,但不同的 DDL 语句不能同时进行。
而并发 DDL 则不同,其允许多条 DDL 语句彼此独立地并发执行。这项能力可以大大提高集群利用率和整体的DDL执行效率。
通过这种区分,用户可以更好地理解在特定场景下应该采取哪种策略来优化 DDL 操作的性能。
并发 DDL 能力
从 OceanBase V4.1.0 版本起,引入了并发 DDL 执行的能力。这一功能通过扩展 RootService 节点的 DDL 线程数量来实现,将单个 DDL 操作分解为不同阶段,并对某些阶段实施并行处理。如此,RootService 可在其节点上处理多个无冲突的 DDL 请求,其新增的 DDL 线程数量与集群规模相关联。随着集群和租户规模的扩展,DDL 执行性能亦相对提升。
OceanBase 数据库具备并发执行能力的 DDL 有:
TRUNCATE TABLE:从 OceanBase V4.1.0 开始支持。CREATE TABLE:从 OceanBase V4.2.1 开始支持。
使用说明与注意事项
集群在 OceanBase V4.2.1 版本或更高版本部署,或由 V4.1.0 升级到 V4.2.1 版本或更高版本后,用户无需任何额外配置即可自动开启并发建表功能。
用户可使用以下 SQL 语句查看当前租户版本状态。
SHOW PARAMETERS LIKE "compatible";
使用并发 DDL 操作需要注意以下事项:
互斥性:并发 DDL 与串行 DDL 在逻辑上完全互斥。为获得并发 DDL 的最大吞吐率,集群在执行并发 DDL 时不应有其他串行 DDL 操作进行。
节点优化:DDL 请求总是在 RootService 节点执行。为降低网络开销,RootService 和租户 Leader 应尽可能置于同一节点。
资源消耗:提升并发 DDL 操作,特别是创建表的并发度,将增加系统负载及资源消耗。
线程需求:系统租户为应对增加的 DDL 请求,需要足够的线程资源。要达到最大吞吐率,系统租户至少需要额外 6 核 CPU 的计算资源。
用户租户资源:用户租户同样需要足够的线程来处理 DDL 请求和写内部表操作。为实现 DDL 最优性能,用户租户需配备至少额外 14 核 CPU 的计算资源。
内存和存储需求:由于并发 DDL 特别是并发表创建会在短时间内向内部表写入大量数据,从而对存储和内存提出更高的要求。当存储空间过小或内存不足以支撑数据快速落盘时,可能会限制写入速度,这将直接影响并发 DDL 的执行效率,同时也会性能影响正常业务流量的处理。