Oracle中基于直方图的连接基数(Join Cardinality)估计算法的关键技术要点:
Join Cardinality = (T1行数 × T2行数) × Join Selectivity
无直方图时
:
1/MAX(NDV1, NDV2)
有直方图时 :基于值分布频率的加权计算
Join Cardinality = SUM[freq_t1(i) × freq_t2(i)]WHERE value_t1(i) = value_t2(i)
特点 :
每个distinct value一个bucket
直接存储每个值的频率
连接计算精确
算法步骤 :
对齐两个直方图的bucket边界
对重叠区间进行选择性估计
假设每个bucket内均匀分布
处理方式 :
Popular values :精确频率匹配
Non-popular values :使用密度(density)估计
-- 示例计算Join Selectivity =
SUM_{匹配值} (freq_t1/total_t1 × freq_t2/total_t2)当连接条件涉及多列时,使用多列统计信息
考虑列间相关性
density = 1 / (NDV × (1 - sum(freq_popular^2)))
当数据分布高度偏斜时,直方图显著改善估计精度
对等值连接尤其重要
等值连接 :直方图效果最佳
范围连接 :使用端点密度估计
外连接 :需要调整基数计算
当统计信息不足时,自动使用动态采样
11g+ 默认对未分析表进行动态采样
-- 创建列组统计BEGIN DBMS_STATS.GATHER_TABLE_STATS( method_opt => 'FOR COLUMNS (col1, col2)' );END;
对连接列且数据偏斜的列收集直方图
避免过度收集直方图(bucket数量控制)
过时统计信息 :导致连接顺序错误
绑定变量窥视 :影响直方图使用
直方图桶数不足 :无法准确描述复杂分布
SELECT column_name, histogram, num_bucketsFROM user_tab_col_statisticsWHERE table_name = 'TABLE_NAME';
ALTER SESSION SET tracefile_identifier = 'join_card';ALTER SESSION SET events 'trace[optimizer.*]';
对于非等值连接:
Join Cardinality = T1_rows × T2_rows × (1 - Π(1 - overlap_ratio(i)))
直方图核心价值 :解决数据偏斜导致的基数估计错误
算法选择 :根据直方图类型采用不同计算方法
实践建议 :
对高频连接列收集适当直方图
监控执行计划中的基数估计与实际行数差异
使用SQL Profile或SPM固定好的执行计划
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/7655508/viewspace-3146065/ ,如需转载,请注明出处,否则将追究法律责任。