Oracle SQL Hint 详解
Oracle SQL Hint 详解
适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
SQL Hint 影响 CBO 决策[1]:
详细见:Oracle SQL Hint 详解。
2. 语法
SELECT /*+ HINT */ ...
INSERT /*+ HINT */ ...
UPDATE /*+ HINT */ ...
DELETE /*+ HINT */ ...
MERGE /*+ HINT */ ...
3. 优化器
3.1 优化模式
/*+ RULE */ -- RBO
/*+ FIRST_ROWS(n) */ -- 前几行快
/*+ FIRST_ROWS_10 */
/*+ FIRST_ROWS_100 */
/*+ FIRST_ROWS_1000 */
/*+ ALL_ROWS */ -- 全部行(吞吐量)
/*+ CHOOSE */ -- 选择
3.2 示例
SELECT /*+ FIRST_ROWS(10) */ * FROM employees WHERE name = 'Alice';
SELECT /*+ ALL_ROWS */ * FROM employees;
4. 索引
4.1 选择
/*+ INDEX(t idx_name) */ -- 指定索引
/*+ INDEX(t) */ -- 任意索引
/*+ INDEX(t idx1 idx2) */ -- 多个
/*+ NO_INDEX(t idx_name) */ -- 不用
/*+ INDEX_FFS(t idx_name) */ -- Fast Full Scan
/*+ INDEX_SS(t idx_name) */ -- Skip Scan
/*+ INDEX_DESC(t idx_name) */ -- 降序
/*+ INDEX_ASC(t idx_name) */ -- 升序
/*+ INDEX_COMBINE(t) */ -- 组合
4.2 示例
SELECT /*+ INDEX(e idx_emp_name) */ * FROM employees e WHERE name = 'Alice';
SELECT /*+ INDEX_FFS(e idx_emp_name) */ name FROM employees e;
5. 表访问
/*+ FULL(t) */ -- 全表扫描
/*+ ROWID(t) */ -- ROWID
/*+ CLUSTER(t) */ -- 簇
/*+ HASH(t) */ -- 哈希
5.1 示例
SELECT /*+ FULL(e) */ * FROM employees e WHERE dept_id = 10;
6. JOIN
6.1 方法
/*+ USE_NL(t1 t2) */ -- Nested Loop
/*+ USE_HASH(t1 t2) */ -- Hash Join
/*+ USE_MERGE(t1 t2) */ -- Sort Merge
/*+ NO_USE_NL(t1 t2) */
/*+ NO_USE_HASH(t1 t2) */
/*+ NO_USE_MERGE(t1 t2) */
6.2 顺序
/*+ LEADING(t1 t2) */ -- 指定顺序
/*+ ORDERED */ -- FROM 顺序
/*+ SWAP_JOIN_INPUTS(t) */ -- 交换输入
6.3 示例
SELECT /*+ USE_HASH(e d) LEADING(e d) */ *
FROM employees e, departments d
WHERE e.dept_id = d.id;
SELECT /*+ USE_NL(e d) */ *
FROM employees e, departments d
WHERE e.dept_id = d.id;
详细见:Oracle JOIN 连接方式。
7. 并行
7.1 并行度
/*+ PARALLEL(t n) */ -- 并行度 n
/*+ PARALLEL(t) */ -- 自动
/*+ NOPARALLEL(t) */ -- 串行
/*+ PARALLEL_INDEX(t idx n) */
7.2 PQ
/*+ PQ_DISTRIBUTE(t, distribution) */
/*+ PQ_FILTER(...) */
7.3 示例
SELECT /*+ PARALLEL(s 8) */ SUM(amount) FROM sales s;
详细见:Oracle 并行查询详解。
8. 子查询
/*+ PUSH_SUBQ */ -- 推进子查询
/*+ NO_PUSH_SUBQ */
/*+ MERGE */ -- 合并视图
/*+ NO_MERGE */
/*+ UNNEST */ -- 展开
/*+ NO_UNNEST */
/*+ STAR_TRANSFORMATION */ -- 星型转换
8.1 示例
SELECT /*+ MERGE(v) */ * FROM (
SELECT * FROM employees
) v;
SELECT /*+ UNNEST(@sub) */ * FROM employees e
WHERE EXISTS (SELECT /*+ QB_NAME(sub) */ 1 FROM departments WHERE id = e.dept_id);
9. 视图
/*+ MERGE(v) */ -- 视图合并
/*+ NO_MERGE(v) */
/*+ PUSH_PRED(v) */ -- 推进谓词
/*+ NO_PUSH_PRED(v) */
10. 数据加载
/*+ APPEND */ -- 直接路径
/*+ APPEND_VALUES */ -- VALUES 直接路径
/*+ NOAPPEND */
10.1 示例
INSERT /*+ APPEND */ INTO big_table SELECT * FROM source;
11. 其他
/*+ DRIVING_SITE(t) */ -- 远程执行
/*+ CARDINALITY(t, n) */ -- 设置基数
/*+ OPT_PARAM(name, value) */ -- 参数
/*+ MONITOR */ -- 监控
/*+ NO_MONITOR */
/*+ GATHER_PLAN_STATISTICS */ -- 统计
/*+ RESULT_CACHE */ -- 结果缓存
/*+ NO_RESULT_CACHE */
/*+ NO_UNNEST */
/*+ RESULT_MODE(...) */
/*+ XMLINDEX_REWRITE */
11.1 示例
SELECT /*+ CARDINALITY(e, 10000) */ * FROM employees e;
SELECT /*+ OPT_PARAM('optimizer_index_cost_adj', 50) */ * FROM employees;
SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM employees;
12. Hint 错误
12.1 不生效
- 语法错误
- 别名错误
- 索引不存在
- 不适用
12.2 检查
-- 查看 Hint 报告(19c+)
SELECT sql_fulltext FROM v$sql ...;
-- 或
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format => 'ALL')));
13. QB_NAME
SELECT /*+ QB_NAME(main) LEADING(@sub e) */ *
FROM employees e
WHERE EXISTS (SELECT /*+ QB_NAME(sub) */ 1 FROM departments WHERE id = e.dept_id);
14. 应用场景
14.1 索引强制
SELECT /*+ INDEX(e idx_emp_email) */ * FROM employees e WHERE email = '...';
14.2 全表
SELECT /*+ FULL(e) */ * FROM employees e WHERE dept_id = 10;
-- 数据量大部分
14.3 JOIN
-- 大表
SELECT /*+ USE_HASH(a b) */ ...
-- 小表
SELECT /*+ USE_NL(a b) */ ...
14.4 并行
SELECT /*+ PARALLEL(t 8) */ COUNT(*) FROM big_table t;
14.5 直接路径
INSERT /*+ APPEND */ INTO target SELECT * FROM source;
15. 替代
15.1 Profile
-- SQL Profile(Hint 等效)
EXEC DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(...);
15.2 Baseline
-- SQL Plan Baseline
EXEC DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(...);
详细见:Oracle SQL 调优顾问、Oracle SQL Plan Baseline 基线。
15.3 统计
- 直方图
- 扩展统计
- 系统
16. 何时使用
- CBO 错误
- 临时解决
- 测试
- 验证假设
16.1 不建议
- 长期
- 数据变化
- 维护
17. 验证
17.1 执行计划
EXPLAIN PLAN FOR SELECT /*+ INDEX(t idx) */ ...;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY));
17.2 实际
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id'));
-- Note 部分 Hint
详细见:Oracle 执行计划详解。
18. 最佳实践
- 谨慎使用:最后手段
- 统计优先:基础
- Profile/Baseline:替代
- 测试:验证
- 注释:说明
- 监控:稳定
- 数据变化:调整
- 版本兼容:检查
- 别名正确:生效
- 文档化:维护
19. 参考资料
[1] Oracle Database SQL Tuning Guide 19c, “Hints” https://docs.oracle.com/en/database/oracle/oracle-database/19/tgsql/influencing-the-optimizer.html