leading提示必须在优化器生成的执行计划明显偏离预期时使用,如驱动表选错致全表扫描暴增;须紧邻select后、用/+ leading(t1 t2) /语法,表名须与from中别名完全一致,且不能违反外连接依赖约束。

LEADING提示什么时候必须用?
当优化器生成的执行计划明显偏离预期,比如该走NESTED LOOPS却选了HASH JOIN,或者驱动表选了大表导致全表扫描次数暴增,这时LEADING就不是“可选”,而是“不得不干预”。典型场景包括:连接字段有高选择性索引但未被利用、统计信息过期、或查询中混用了外连接与内连接导致优化器误判驱动顺序。
LEADING怎么写才不被忽略?
LEADING必须放在SELECT关键字后紧邻位置,且括号内表名必须和FROM子句中出现的**实际表名或别名**完全一致(大小写敏感,若未加双引号则默认大写)。常见错误包括:
- 在
FROM里用了别名a,但LEADING(a b)里写的是原表名table_a - 多个外连接混合时,
LEADING指定的顺序违反了外连接依赖约束(例如RIGHT JOIN右边表不能当第一个驱动表) - 没加
/*+ */注释包裹,写成LEADING(t1 t2)直接报错
正确写法示例:
SELECT /*+ LEADING(e d) */ e.ename, d.dname<br>FROM emp e, dept d<br>WHERE e.deptno = d.deptno;
LEADING和ORDERED提示有什么区别?
LEADING(t1 t2 t3)只指定前导表顺序,后续连接仍由优化器决定;而ORDERED强制按FROM子句中出现的**物理顺序**逐个连接,更激进。实际中优先用LEADING,除非你明确需要控制每一步的连接对象(比如中间结果集必须先和某张维度表关联再过滤)。另外,ORDERED会禁用部分连接重排优化,可能掩盖更优路径。
为什么加了LEADING还是没生效?
最常被忽略的三点:
- 目标表没出现在
FROM子句顶层——比如用子查询包裹了某张表,LEADING无法穿透子查询作用域 - 存在
UNION ALL或MATERIALIZE等改写操作,导致原始表顺序被重排 - 优化器模式被设为
RULE(已废弃),或OPTIMIZER_FEATURES_ENABLE版本太低(低于10g)
验证是否生效,直接看执行计划中的Rows列和Operation缩进层级:NESTED LOOPS下第一层子操作对应的就是LEADING指定的第一个表。
LEADING失去作用的隐式重写,比如物化视图重写、SQL Profile 自动改写,或者 DBA 启用了_optimizer_ignore_hints=TRUE这类隐藏参数。











