Oracle 12c 直方图算法深度解析:AUTO_SAMPLE_SIZE 下的四大类型判定逻辑

在 Oracle 12c 及以后版本中,直方图的诞生过程远比 DBMS_STATS 文档中描述得要复杂。Oracle 并非简单地“看 NDV 是否超过桶数”,而是通过一个多阶段决策树,结合 NDV、重复值频率分布、采样比例 (estimate_percent) 以及内部阈值 p,来决定最终生成 Frequency、Top-Frequency、Height-Balanced 还是 Hybrid 直方图。 本文用实验+公式的方式,把官方文档中一句带过的“Oracle 数据库使用多个条件”彻底拆开讲透。


1. 四个关键变量

符号全称来源说明
NDVNumber of Distinct Values列统计信息去重后实际有多少个值。
nhistogram bucketsMETHOD_OPT SIZE SKEWONLY 或默认默认 254,最大 2048。
pinternal percent threshold固定公式p = (1 – 1/n) * 100;当 n=254 时 p=99.6。
estimate_percent采样比例DBMS_STATS.GATHER_TABLE_STATS默认 AUTO_SAMPLE_SIZE(即让 Oracle 自己决定)。

2. 四种直方图判定流程图

下面这张决策树,就是 Oracle 在 AUTO_SAMPLE_SIZE 下真正跑的逻辑,先后顺序不能调换。

是否是否是否开始收集列统计信息NDV <= n ?生成 **Frequency** 直方图存在某个值出现的频率 >= p ?生成 **Top-Frequency** 直方图estimate_percent = AUTO_SAMPLE_SIZE ?生成 **Hybrid** 直方图生成 **Height-Balanced** 直方图

注:

  1. estimate_percent ≠ AUTO_SAMPLE_SIZE 时,Hybrid 会被降级为 Height-Balanced。
  2. 12cR1 以前没有 Top-Frequency 与 Hybrid,直接走 Height-Balanced。

3. 案例推演:把公式跑一遍

场景设定

  • ORDERS.ORDER_STATUS
  • NDV = 5 (NEW, PAID, SHIPPED, DONE, CANCEL)
  • 总行数 1 000 000
  • 默认桶数 n = 254
  • estimate_percent = AUTO_SAMPLE_SIZE(默认)

3.1 计算 p

p = (1 – 1/254) * 100 ≈ 99.606%

3.2 计算各值出现频率

行数频率
NEW100.001%
PAID995 00099.5%
SHIPPED3 0000.3%
DONE1 9600.196%
CANCEL300.003%

3.3 走决策树

  1. NDV <= n ? 5 ≤ 254 ✔️ → 如果所有值都能被桶装下,Oracle 会先生成 Frequency 直方图。 但此处 PAID 一行占了 99.5%,其他值频率极低,Oracle 会进一步判断是否符合 Top-Frequency 条件。
  2. 存在值频率 >= p ? 99.5% < 99.606% ❌,因此不会触发 Top-Frequency。
  3. estimate_percent = AUTO_SAMPLE_SIZE ? 是 ✔️ → 最终生成 Hybrid 直方图(Top-N 频率 + 桶内分布)。

4. 小结:一句话记流程

“NDV 少就走 Frequency,有超阈值热门值就走 Top-Frequency,AUTO_SAMPLE_SIZE 下 NDV 太多就 Hybrid,否则退回 Height-Balanced。”


5. 实用脚本:现场验证你的列会生成哪种直方图

-- 1. 查看当前列的 NDV、桶数、estimate_percent
SELECT column_name, num_distinct, histogram, num_buckets
FROM   user_tab_col_statistics
WHERE  table_name = 'ORDERS'
AND   column_name = 'ORDER_STATUS';

-- 2. 强制收集并观察直方图类型
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
    ownname          => user,
    tabname          => 'ORDERS',
    method_opt       => 'FOR COLUMNS ORDER_STATUS SIZE 254',
    estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);
END;
/

如果本文帮你把「Oracle 到底怎么选直方图」彻底讲清,欢迎收藏、转发,让更多 DBA 少走弯路!

发表评论

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

滚动至顶部