/+ APPEND / 未加速或报错因触发直接路径插入需满足硬性条件:无启用触发器、非 IOT、无外键引用、不在同一事务中混用常规 DML;常见 ORA-12838 错误即由此引发。
为什么 /*+ APPEND */ 有时没加速,甚至报错
因为 /*+ append */ 触发的是直接路径插入(direct-path insert),它绕过缓冲区、不走 undo、不生成重做日志(除非开启force logging),但前提是表必须满足几个硬性条件:不能有启用的触发器、不能是索引组织表(iot)、不能有外键约束引用该表、且当前会话不能在事务中已对该表做过常规 dml。
常见错误现象:ORA-12838: cannot read/modify an object after modifying it in parallel 或直接忽略提示走常规路径——往往是因为你刚执行过 INSERT INTO t VALUES (……),再执行/*+ APPEND */ 就会失败。
- 确认表状态:
SELECT triggers_enabled, iot_type FROM user_tables WHERE table_name = 'YOUR_TABLE' - 禁用触发器(临时):
ALTER TABLE t DISABLE ALL TRIGGERS(别忘了事后启用) - 避免在同一个事务里混用常规插入和
/*+ APPEND */ - 如果表有唯一索引,
/*+ APPEND */仍可工作,但索引维护会拖慢整体速度——此时考虑先DISABLE INDEX,插入完再REBUILD
INSERT /*+ APPEND */和 INSERT /*+ APPEND_VALUES */ 怎么选
/*+ APPEND_VALUES */是 11g 引入的变种,专用于单条或少量 VALUES 子句的场景,比如批量插几十行;而纯 /*+ APPEND */ 更适配 SELECT 来源的大批量加载。两者底层都走直接路径,但解析行为不同。
容易踩的坑:用 /*+ APPEND_VALUES */ 插上千行 VALUES 列表,性能反而比循环调用 INSERT /*+ APPEND */ SELECT …… FROM DUAL 差——因为 SQL 硬解析压力大,且 Oracle 对 VALUES 列表长度敏感,超长会退化为常规路径。
- 插≤100 行:用
/*+ APPEND_VALUES */,写法干净 - 插≥1000 行:改用
INSERT /*+ APPEND */ SELECT …… FROM (VALUES ……, ……, ……)或拆成多个批次 - 注意绑定变量限制:
/*+ APPEND_VALUES */不支持绑定变量,所有值必须字面量
直接路径插入后数据“看不见”?不是没插进去,是没提交 + 没刷新
直接路径插入的数据写入高水位线(HWM)之上,不经过 Buffer Cache,所以其他会话即使 SELECT 也查不到,直到你 COMMIT。更隐蔽的问题是:即使你COMMIT 了,某些工具(如旧版 SQL Developer)可能缓存了统计信息或执行计划,显示行数为 0。
验证是否真成功,别只看 SELECT COUNT(*),优先查USER_TAB_STATISTICS 或直接SELECT /*+ FULL(t) */ COUNT(*) FROM t(强制全表扫)。
- 必须显式
COMMIT,AUTOCOMMIT在 SQL*Plus 里默认关着 - 插入后立刻查,加
/*+ FULL */提示防止走索引扫描漏掉新数据 - 如果用了
NOLOGGING,备份策略要调整——归档日志里没有这部分变更
比 APPEND 更快的替代方案:DBMS_PARALLEL_EXECUTE和外部表
当单次 INSERT /*+ APPEND */ 仍卡在 IO 或 CPU 上,说明瓶颈不在 SQL 层,而在数据准备或单线程吞吐。这时候强行加并行不一定有效——Oracle 并行 DML 需要额外许可,且对小表反而有害。
真正适合大批量落地的组合是:把数据先卸到文件(CSV/Oracle dump),建外部表(CREATE TABLE t_ext …… ORGANIZATION EXTERNAL),再用 INSERT /*+ APPEND PARALLEL(4) */ 从外部表加载。这样 IO 和解析完全解耦,还能复用已有 ETL 流程。
- 外部表路径必须是数据库服务器本地目录,且
ORACLE_DIR对象已创建并授权 -
DBMS_PARALLEL_EXECUTE适合无法一次性读入内存的超大表,按 ROWID 分块,但要注意事务边界和错误处理粒度 - 别迷信“并行越多越快”,实测 4~8 个并行度在多数 OLTP 库上已达 IO 饱和点
直接路径的核心代价是灵活性换速度:它省掉了 UNDO、REDO、约束检查、触发器等所有“安全网”。一旦出错,回滚不了,只能删数据重来。所以生产环境用之前,务必在同等数据量级的测试库跑通全流程,尤其关注索引失效、统计信息陈旧、以及备份窗口是否被压缩。






























