Oracle 12c 新特性:直方图的「自动驾驶」——METHOD_OPT SIZE AUTO 实战笔记

在 11g 及以前,DBA 需要手工指定哪些列需要直方图,既枯燥又容易遗漏。 从 Oracle 12c 开始,METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO' 引入了一种「按需创建直方图」的机制: 只有当某列真正被查询用到,并且优化器认为直方图会改善执行计划时,才在下次收集统计信息时自动为该列创建直方图。

原理速览

阶段动作关键数据字典
1使用 SIZE AUTO 收集统计信息无直方图,但标记了“可自动创建”
2应用发出带谓词的 SQL优化器把谓词写入 SYS.COL_USAGE$
3再次 GATHER_*_STATSDBMS_STATS 读取 COL_USAGE$,若发现某列“值得”直方图,则 HISTOGRAM_ONLY 创建之

实验:5 分钟复现官方 Demo

1. 准备测试表

-- 外部表 sh_ext 已存在,结构与 sh.sales 相同
CREATE TABLE sales2 AS SELECT * FROM sh_ext;

-- 创建常规索引
CREATE INDEX sh_12c_idx1 ON sales2(prod_id);
CREATE INDEX sh_12c_idx2 ON sales2(cust_id, time_id);

2. 初次收集统计信息(无直方图)

BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
    ownname   => USER,
    tabname   => 'SALES2',
    method_opt=> 'FOR ALL COLUMNS SIZE AUTO');
END;
/

查看结果——所有列均为 NONE

SELECT column_name, notes, histogram
FROM   user_tab_col_statistics
WHERE  table_name = 'SALES2';

3. 执行一次“生产查询”

SELECT COUNT(*)
FROM   sales2
WHERE prod_id = 42;

该 SQL 会把 prod_id 记录到 SYS.COL_USAGE$

4. 再次收集统计信息

BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
    ownname   => USER,
    tabname   => 'SALES2',
    options   => 'GATHER AUTO');
END;
/

5. 验证直方图已出现

SELECT column_name, notes, histogram
FROM   user_tab_col_statistics
WHERE  table_name = 'SALES2';
COLUMN_NAMENOTESHISTOGRAM
PROD_IDHISTOGRAM_ONLYFREQUENCY
NONE

常见问题

  1. 为什么数据没变,执行计划却变了? 因为 COL_USAGE$ 中记录了新的谓词,下次收集时直方图被创建/删除,优化器有了更精确的 NDV 分布信息,可能选择全表扫或索引扫。
  2. 如何查看列使用率? SELECT * FROM sys.col_usage$ WHERE obj# = (SELECT object_id FROM user_objects WHERE object_name=’SALES2′);需 DBA 权限。
  3. 能否关闭该功能?METHOD_OPT 改为 SIZE 1REPEAT,或者使用 FOR ALL COLUMNS SIZE SKEWONLY 以回到 11g 行为。
  4. 分区表是否适用? 适用。GATHER AUTO 在分区级统计信息收集时同样会检查 COL_USAGE$

踩坑与最佳实践

场景建议
性能测试环境在跑 TPCH/生产回放脚本前,先 GATHER AUTO 一次,避免后期直方图突变导致计划抖动。
ETL 批量加载DBMS_STATS.SET_TABLE_PREFSMETHOD_OPT 临时改为 SIZE 1,加载后再改回 SIZE AUTO
升级后体检升级 12c 或 19c 后,跑 DBMS_STATS.GATHER_DICTIONARY_STATS 并观察 DBA_TAB_COL_STATISTICS.HISTOGRAM 变化。

把直方图的创建权交给 Oracle,让统计信息随真实工作负载“自适应”——这就是 SIZE AUTO 的魅力与风险。 理解 COL_USAGE$ 的生命周期,才能真正玩转 12c+ 的统计信息自动驾驶模式。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部