在 Oracle 12c 及以后版本中,直方图的诞生过程远比
DBMS_STATS
文档中描述得要复杂。Oracle 并非简单地“看 NDV 是否超过桶数”,而是通过一个多阶段决策树,结合 NDV、重复值频率分布、采样比例 (estimate_percent
) 以及内部阈值p
,来决定最终生成 Frequency、Top-Frequency、Height-Balanced 还是 Hybrid 直方图。 本文用实验+公式的方式,把官方文档中一句带过的“Oracle 数据库使用多个条件”彻底拆开讲透。
1. 四个关键变量
符号 全称 来源 说明 NDV Number of Distinct Values 列统计信息 去重后实际有多少个值。 n histogram buckets METHOD_OPT SIZE SKEWONLY
或默认默认 254,最大 2048。 p internal 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** 直方图注:
- 当
estimate_percent ≠ AUTO_SAMPLE_SIZE
时,Hybrid 会被降级为 Height-Balanced。- 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 计算各值出现频率
值 行数 频率 NEW 10 0.001% PAID 995 000 99.5% SHIPPED 3 000 0.3% DONE 1 960 0.196% CANCEL 30 0.003% 3.3 走决策树
- NDV <= n ? 5 ≤ 254 ✔️ → 如果所有值都能被桶装下,Oracle 会先生成 Frequency 直方图。 但此处 PAID 一行占了 99.5%,其他值频率极低,Oracle 会进一步判断是否符合 Top-Frequency 条件。
- 存在值频率 >= p ? 99.5% < 99.606% ❌,因此不会触发 Top-Frequency。
- 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 少走弯路!