什么是直方图?
直方图就是柱状图,表现了表中某一列不同键值的数据的分布情况。 (例如:性别列 男有多少行,女有多少个行)
直方图分为 频率直方图 和 等高直方图
直方图最多只能有254个捅。如果列上的唯一值多余254个,就会出现一个桶放多个值的情况。
直方图相关的影响:
1、Oracle怎么判断一个sql是否要走索引:如果一条sql返回的行数是表的5%以内,那么Oracle就选择走索引。如果是5%以上,Oracle就不选择走索引。
2、在没有统计信息的表中,Oracle通过动态采样来判断应不应该走索引。
3、如果收集了统计信息,但是没有直方图的话。返回结果集的计算可能是不准确的。CBO会用 总行数/基数 来算出来返回的结果集数量(当数据分布倾斜的时候,这种计算是存在很大问题的)。如果列上没有直方图,CBO就认为列上的数据是分布均衡的。
4、查看统计信息的相关视图: dba_table(num_rows) dba_tab_col_statistics(table_name,column_name,num_distinct,histogram,num_buckets,last_analyzed)
5、列的基数很低的话,一般数据分布就会不均衡,要收集直方图。对于选择性很好的列和主键列,不收集直方图是没有影响的。
试验:
1、创建一张表并在OWNER上创建索引。
create table test as select * from sys.dba_objects;
create index idx_test_owner on test(owner);
2、在没有统计信息的情况下 select * from test where OWNER='SYS';
优化器用动态采样,预计表的返回行数为55242,采用全表扫描的方式
3、收集统计信息但是不收集直方图:select * from test where OWNER='SYS';
execute dbms_stats.gather_table_stats(ownname => 'SCOTT',tabname => 'TEST' ,method_opt => 'for all columns size 1');
CBO选择走索引了,为什么呢? 我们来看一下表的统计信息。
select a.column_name,b.num_rows,a.num_distinct,a.histogram,a.num_buckets from dba_tab_col_statistics a,dba_tables b where a.owner = b.owner and a.table_name=b.table_name and a.owner='&owner' and a.table_name='&tablename';
表有8W行,OWNER列有26个唯一值,那么在没有直方图的情况下,Oracle认为列上的数据分布是均匀的。 结果集应该返回 84664/26=3256行, 3256/84664=3.8% 返回的行数为总行数的3.8%,小于5%。所以CBO选择走索引。
4、收集统计信息,收集直方图:select * from test where owner='SYS';
begin dbms_stats.gather_table_stats (ownname => 'SCOTT', tabname => 'TEST' , method_opt => 'for all columns size skewonly', estimate_percent => 100, no_invalidate => false, cascade =>true); end; /
统计信息:
执行计划:
此时 CBO选择了走全表扫描,因为直方图中记录了列中值的分布情况,准确的评估出了OWNER='SYS'的列有37830行,占整个行数的比例绝对超过了5%。所以CBO选择走全表扫描。
总结:
可见直方图记录了列上的数据分布,避免了CBO在数据倾斜的情况下选择错误的执行计划,是很重要的一个东西。