优先选用CREATE_CHUNKS_BY_ROWID,因其按ROWID连续切块、不依赖业务字段、避免全表扫描、执行计划稳定;需确保非IOT/临时表、job_queue_processes>0、CHUNK_SIZE设为5000–50000,并验证dba_parallel_execute_chunks中STATUS='ASSIGNED'。

直接结论:用 CREATE_CHUNKS_BY_ROWID,别碰 CREATE_CHUNKS_BY_NUMBER_COL 或 SQL 切分,除非你明确知道业务字段分布且已排除空值、负数、跳跃等风险。
为什么优先选 CREATE_CHUNKS_BY_ROWID?
它不依赖任何业务逻辑字段,按物理存储(ROWID)连续切块,避免全表扫描统计、跳过索引失效、执行计划稳定。只要表不是索引组织表(IOT)或临时表,就可用。
常见错误现象:ORA-29400: data cartridge error CHUNKING BY ROWID NOT SUPPORTED FOR THIS TABLE TYPE —— 遇到这个错,先查 dba_tables.table_type,确认不是 IOT 或 GLOBAL TEMPORARY。
-
CHUNK_SIZE建议设为 5000–50000 行:太小(如 100)会导致调度开销压倒实际工作;太大(如 50 万)会让单 chunk 失败后重试成本过高 - 切完立刻查
dba_parallel_execute_chunks,确认STATUS = 'ASSIGNED'且CHUNK_ID连续无空缺——这是验证切分成功的唯一可靠方式 - 必须确保
job_queue_processes > 0(建议设为 1000),否则任务创建成功但永不执行
CREATE_CHUNKS_BY_NUMBER_COL 的坑在哪?
它靠字段最大/最小值做线性分段,表面简单,实则脆弱。比如字段是 ORDER_ID,但中间有大量删除、跳号、负数、NULL,切出来的 chunk 就会严重不均,甚至漏数据。
- 字段必须是
NUMBER类型,且NOT NULL(或提前WHERE col IS NOT NULL过滤) - 如果字段存在长尾分布(如 90% 数据集中在 1–1000 范围,剩下 10% 分散在 100000+),chunk 会一边极重、一边极轻
- 无法跨分区对齐:若表已分区,该方式仍按全局值切分,可能把同一分区的数据打散到多个 chunk,破坏局部性
执行前必须检查的三件事
很多人卡在“任务建了但没跑”,其实问题出在初始化阶段。
- 用户需具备
CREATE JOB和EXECUTE ON DBMS_SQL权限——少了任一个,CREATE_TASK可能成功,但后续调用直接报ORA-01031: insufficient privileges -
parallel参数在DBMS_PARALLEL_EXECUTE.RUN_TASK中必须显式设为TRUE,写成FALSE或省略都会退化为串行 - 切块后不要直接
COMMIT,先手动运行一两个 chunk 测试逻辑(用EXECUTE_TASK指定CHUNK_ID),确认 DML 正确、无约束冲突、无触发器干扰
容易被忽略的并发安全细节
DBMS_PARALLEL_EXECUTE 本身不加锁,所有 chunk 是并行独立执行的。这意味着:
- 如果你的 DML 涉及同一行(比如多 chunk 更新同一批主键),会触发
ORA-00060: deadlock detected,而不是静默覆盖 - 目标表上有
ENABLED触发器时,每个 chunk 都会触发一次——不是“只触发一次”,这点和普通 DML 不同 - 事务隔离靠 chunk 粒度:一个 chunk 内部是单事务,chunk 之间完全独立,所以不能依赖跨 chunk 的一致性校验逻辑


















