merge into比update快的根本原因是oracle优化器为其生成的执行计划更高效:update常走nested loops导致重复扫描,merge默认用hash join实现单次全表扫描匹配。

为什么Merge Into比Update快:执行计划决定一切
根本原因不是语法本身,而是Oracle优化器为 MERGE INTO 生成的执行计划天然更高效。传统 UPDATE 带子查询时,优化器常选 NESTED LOOPS,对目标表每行都触发一次源表扫描;而 MERGE INTO 默认倾向 HASH JOIN,两张表各扫一次即可完成全部匹配与更新。
看懂关键执行计划差异
对比两者的 EXPLAIN PLAN 输出,重点盯住这几处:
-
UPDATE执行计划中通常出现重复嵌套:外层TABLE ACCESS FULL(目标表) + 内层反复的TABLE ACCESS FULL或INDEX RANGE SCAN(源表),Rows列显示“per execution”次数飙升 -
MERGE INTO执行计划里几乎总能看到单次VIEW(来自USING子句)+ 单次TABLE ACCESS FULL(目标表)+ 一个HASH JOIN节点,Cost和Consistent Gets显著更低 - 特别注意
Predicate Information:如果UPDATE的子查询条件落在FILTER而非JOIN位置,说明它没走真正关联,纯靠循环过滤
哪些Update写法最容易被Merge Into加速
不是所有 UPDATE 都值得改,以下场景改写后收益最明显:
-
UPDATE t1 SET col = (SELECT col FROM t2 WHERE t2.id = t1.id)—— 典型的“每行查一次”,MERGE INTO直接转成哈希关联 -
UPDATE t1 SET ... WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.ref = t1.id)——EXISTS子查询本身不带更新值,但常伴随额外逻辑开销,MERGE可一并收口 - 源数据来自复杂视图或临时表(如Excel导入后的
WX_USER_TMP),且目标表无强索引支撑子查询时,MERGE避免了重复解析和驱动路径震荡
容易踩的坑和绕不开的限制
别只盯着快,这几个硬约束不处理好会直接报错或结果错乱:
-
ON子句里不能更新被引用的列,否则报ORA-38104。比如ON (t1.id = t2.id),就不能在WHEN MATCHED THEN UPDATE SET t1.id = ... -
USING子句返回的记录必须对目标表键值唯一,否则可能触发ORA-30926(无法在源中获得稳定行集)。加GROUP BY或用ROW_NUMBER() OVER (PARTITION BY ...)去重是常见解法 - 想用并行加速?得给目标表加
/*+ PARALLEL(t1, 4) */提示,但要注意USING源是否支持并行扫描,否则提示会被忽略
真正卡住人的往往不是语法,而是把子查询逻辑安全、确定性地“搬进” USING 和 ON——这一步没对齐,再快的执行计划也救不了数据一致性。











