/+ 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、约束检查、触发器等所有“安全网”。一旦出错,回滚不了,只能删数据重来。所以生产环境用之前,务必在同等数据量级的测试库跑通全流程,尤其关注索引失效、统计信息陈旧、以及备份窗口是否被压缩。











