Oracle 优化器(CBO)原理
Oracle 优化器(CBO)原理
适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
优化器(Optimizer) 选择最优执行计划[1]:
| 类型 | 说明 |
|---|---|
| RBO | 基于规则(已废弃) |
| CBO | 基于成本(默认) |
2. CBO 基础
2.1 成本模型
Cost = IO Cost + CPU Cost
2.2 基数估算
Cardinality = 表行数 × 选择率
2.3 选择率
- 等值:1 / NDV
- 范围:1 / 3
- BETWEEN:1 / 12
3. 统计信息
3.1 表统计
SELECT table_name, num_rows, blocks, avg_row_len
FROM user_tables WHERE table_name = 'EMPLOYEES';
3.2 列统计
SELECT column_name, num_distinct, density, num_nulls, low_value, high_value
FROM user_tab_col_statistics
WHERE table_name = 'EMPLOYEES';
3.3 索引统计
SELECT index_name, blevel, leaf_blocks, distinct_keys, clustering_factor
FROM user_indexes
WHERE table_name = 'EMPLOYEES';
3.4 直方图
SELECT table_name, column_name, histogram
FROM user_tab_col_statistics
WHERE histogram != 'NONE';
4. 聚簇因子(Clustering Factor)
4.1 含义
- 索引行与表行的物理顺序相似度
- 低:索引有效
- 高:索引低效
4.2 查看
SELECT index_name, clustering_factor
FROM user_indexes
WHERE table_name = 'EMPLOYEES';
4.3 优化
- 排序数据加载
- 重建表
- 分区
5. 直方图
5.1 类型
| 类型 | 说明 |
|---|---|
| FREQUENCY | 频率(< 254 NDV) |
| HEIGHT BALANCED | 高度平衡(≥ 254 NDV) |
5.2 适用
- 数据倾斜
- 等值查询
5.3 创建
EXEC DBMS_STATS.GATHER_TABLE_STATS(
'SCOTT', 'EMPLOYEES',
method_opt => 'FOR COLUMNS dept_id SIZE 254'
);
6. 绑定变量窥视
6.1 9i+ 默认
- 第一次执行窥视绑定值
- 生成执行计划
6.2 问题
- 数据倾斜:不同值需要不同计划
6.3 自适应游标(11g+)
-- 查看绑定敏感性
SELECT sql_id, child_number, bind_sensitive, bind_aware
FROM v$sql
WHERE sql_id = '&sql_id';
7. 优化器参数
7.1 OPTIMIZER_MODE
ALTER SYSTEM SET optimizer_mode = ALL_ROWS SCOPE=SPFILE;
-- ALL_ROWS: 优化吞吐
-- FIRST_ROWS_n: 优化响应(1/10/100/1000)
-- FIRST_ROWS: 向后兼容
7.2 OPTIMIZER_FEATURES_ENABLE
ALTER SYSTEM SET optimizer_features_enable = '19.1.0';
7.3 OPTIMIZER_INDEX_COST_ADJ
-- 索引成本调整(默认 100)
ALTER SESSION SET optimizer_index_cost_adj = 50;
-- 越小越倾向用索引
7.4 OPTIMIZER_INDEX_CACHING
-- 索引缓存率(默认 0)
ALTER SESSION SET optimizer_index_caching = 90;
7.5 DB_FILE_MULTIBLOCK_READ_COUNT
ALTER SYSTEM SET db_file_multiblock_read_count = 16;
8. 动态采样
8.1 启用
ALTER SESSION SET optimizer_dynamic_sampling = 2;
-- 0: 关闭
-- 2: 默认
-- 11: 最高
8.2 应用
- 缺少统计信息
- 临时表
- 复杂查询
8.3 HINT
SELECT /*+ DYNAMIC_SAMPLING(e 4) */ * FROM employees e;
9. HINT 详解
9.1 优化器
/*+ ALL_ROWS */
/*+ FIRST_ROWS(10) */
/*+ RULE */ -- RBO
9.2 访问路径
/*+ FULL(table) */
/*+ INDEX(table idx_name) */
/*+ INDEX_FFS(table idx_name) */
/*+ NO_INDEX(table) */
/*+ INDEX_DESC(table idx_name) */
9.3 JOIN
/*+ USE_NL(t1 t2) */
/*+ USE_HASH(t1 t2) */
/*+ USE_MERGE(t1 t2) */
/*+ LEADING(t1) */
/*+ ORDERED */
/*+ SWAP_JOIN_INPUTS(t2) */
9.4 其他
/*+ PARALLEL(t 4) */
/*+ APPEND */ -- 直接路径插入
/*+ CARDINALITY(t 1000) */
/*+ DYNAMIC_SAMPLING(t 4) */
/*+ MONITOR */
10. SQL Profile
10.1 生成
DECLARE
v_task VARCHAR2(100);
BEGIN
v_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => '&sql_id');
DBMS_SQLTUNE.EXECUTE_TUNING_TASK(v_task);
END;
/
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('&task_name') FROM dual;
10.2 接受
EXEC DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(
task_name => '&task_name',
name => 'my_profile'
);
10.3 管理
-- 查看
SELECT * FROM dba_sql_profiles;
-- 删除
EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('my_profile');
11. SQL Plan Baseline
11.1 捕获
ALTER SYSTEM SET optimizer_capture_sql_plan_baselines = TRUE;
11.2 查看
SELECT * FROM dba_sql_plan_baselines;
11.3 演进
-- 测试新计划
EXEC DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(sql_handle => '&handle');
12. 10053 事件
12.1 优化器决策
ALTER SESSION SET events '10053 trace name context forever, level 1';
EXPLAIN PLAN FOR SELECT ...;
ALTER SESSION SET events '10053 trace name context off';
12.2 内容
- 表统计
- 索引统计
- 成本计算
- 计划选择
13. 常见坑与排错
13.1 CBO 选错计划
-- 1. 收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS(...);
-- 2. 加 HINT
-- 3. SQL Profile
-- 4. SQL Plan Baseline
13.2 统计信息过期
-- 自动收集
SELECT * FROM dba_autotask_client;
-- 手动
EXEC DBMS_STATS.GATHER_SCHEMA_STATS('SCOTT');
13.3 数据倾斜
-- 直方图
method_opt => 'FOR COLUMNS col SIZE 254'
14. 最佳实践
- 定期收集统计信息:CBO 准确
- 直方图处理倾斜:精确
- 绑定变量:减少硬解析
- HINT 谨慎:仅必要时
- SQL Profile:自动优化
- SQL Plan Baseline:稳定计划
- 10053 诊断:决策分析
- 动态采样:临时表
- 测试不同计划:选择最优
- 监控性能:持续优化
15. 参考资料
[1] Oracle Database SQL Tuning Guide 19c, “Optimizer” https://docs.oracle.com/en/database/oracle/oracle-database/19/tgsql/optimizer-statistics.html