什么是直方图?

直方图就是柱状图,表现了表中某一列不同键值的数据的分布情况。  (例如:性别列   男有多少行,女有多少个行)

直方图分为  频率直方图  和   等高直方图

 

 

 

直方图最多只能有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在数据倾斜的情况下选择错误的执行计划,是很重要的一个东西。