直方图(histograms)
默认情况下,在收集表的统计信息信息时,对列信息的收集是FOR ALL COLUMNS SIZE AUTO,这种情况下直方图的信息可能没有收集到,所以可以手工指定收集直方图的信息:
exec DBMS_STATS.GATHER_table_STATS(OWNNAME => 'ICD', TABNAME => 'TAGENTOPRINFO', METHOD_OPT =>'FOR all COLUMNS');
4.1 直方图上列的信息说明
直方图就是列分析中 数据在列上的分布情况。可以使用如下SQL 查看表列上的直方图信息。
- /* Formatted on 2011/11/25 12:51:33(QP5 v5.185.11230.41888) */
- SELECT column_name AS "NAME",
- num_distinct AS "#DST",
- low_value,
- high_value,
- density AS "DENS",
- num_nulls AS "#NULL",
- avg_col_len AS "AVGLEN",
- histogram,
- num_buckets AS "#BKT"
- FROM user_tab_col_statistics
- WHERE table_name = 'T';
相关字段的解释如下:
num_distinct:该列中唯一值的数量
low_value:该列的最小值,显示内部存储格式
high_value:该列的最大值,显示内部存储格式
num_nulls:该列中存储的null的总数
avg_col_len:平均列大小,以字节表示
histogram:表明是否有直方图统计信息,如果有,是哪种类型。
NONE表示没有,
frequency表示频率类型,
height balanced表示平均分布类型,此列在10g以后提供
num_buckets:直方图里的桶数,统计信息中所谓的桶或类,就是一组同类的数值放在一起。直方图至少由一个桶组成。如果没有直方图,桶数为1.最大桶数是254
这里重点看一些density列,在asktom论坛上有一篇帖子说明。
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2969235095639
把这个帖子摘下来了,放在:http://blog.csdn.net/cymm_liu/article/details/7882290
4.2 直方图类型说明
当Oracle 做直方图分析时,会将要分析的列上的数据分成很多数量相同的部分,每一部分称为一个bucket,这样CBO就可以非常容易地知道这个列上的数的分布情况,这种数据的分布将作为一个非常重要的因素纳入到执行计划成本的计算当中。
Oracle 有两种类型的直方图: height-balanced histograms and frequency histograms.
直方图的信息存储在DBA_TAB_COL_STATISTICS和USER_ TAB_COL_STATISTICS 视图中。
视图中的histogram列有如下三种值: HEIGHT BALANCED, FREQUENCY, NONE.
4.2.1 Height-Balanced Histograms
在高度平衡的直方图中, 列的值被分入一些bands中,每个band 包含差不多的rows数。这个band 也称为bucket。 即在一个bucket内,记录基本上是一样的。
假如一个列ID的值是1到100,histogram 有10个buckets。
如果数据是均匀分布的,那么它的直方图就类似与:
每个bucket中的记录数都是表中总数的十分之一。
如果数据是非均匀分布的,那么它的直方图就类似与:
在这个实例中,绝大多数的记录值都是5. 只有1/10的值在60到100之间。
测试:
SQL> create table bhh(id number);
SQL> declare
2 i number;
3 begin
4 for i in 1..100 loop
5 insert into bhh values(i);
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> commit;
Commit complete.
SQL> select count(*) from bhh;
COUNT(*)
----------
100
--默认情况下,在收集表的统计信息信息时,是FOR ALL COLUMNS SIZE AUTO
这里为了显示效果,我们手工指定收集列的信息
exec DBMS_STATS.GATHER_table_STATS (OWNNAME => 'SYS', TABNAME => 'BHH', METHOD_OPT => 'FOR COLUMNS SIZE 10 ID');
--10是我们buckets的数量,ID 是我们要收集列的名称。
SQL> SELECT column_name, num_distinct, num_buckets, histogram
2 FROM DBA_TAB_COL_STATISTICS WHERE table_name = 'BHH' AND column_name = 'ID';
COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM
------------------------------ ------------ ----------- ---------------
ID 100 10 HEIGHT BALANCED
SQL> SELECT endpoint_number, endpoint_value
2 FROM USER_HISTOGRAMS
3 WHERE table_name = 'BHH' and column_name = 'ID'
ORDER BY endpoint_number;
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
0 1
1 11
2 21
3 31
4 41
5 51
6 61
7 71
8 81
9 91
10 100
11 rows selected.
4.2.2 Frequency Histograms
在Frequency Histograms 里,每个bucket 只包含一个记录。 因此当表记录中distinct values 小于等于histograms buckets时,会创建Frequency histograms 会自动创建。
示例:
SQL> create table fh(id number);
Table created.
SQL> declare
2 i number;
3 j number;
4 begin
5 for i in 1..10 loop
6 for j in 1..10 loop
7 insert into fh values(j);
8 end loop;
9 end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
SQL> select count(*) from fh;
COUNT(*)
----------
100
SQL> BEGIN
DBMS_STATS.GATHER_table_STATS (OWNNAME => 'SYS', TABNAME => 'FH', METHOD_OPT => 'FOR COLUMNS SIZE 100 ID');
END;
/
--创建100个bucket,这样每个bucket 就只有一个row了。
SQL> SELECT column_name, num_distinct, num_buckets, histogram
2 FROM USER_TAB_COL_STATISTICS
3 WHERE table_name = 'FH' AND column_name = 'ID';
COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM
------------------------------ ------------ ----------- ---------------
ID 10 10 FREQUENCY
SQL> SELECT endpoint_number, endpoint_value
2 FROM USER_HISTOGRAMS
3 WHERE table_name = 'FH' and column_name = 'ID'
ORDER BY endpoint_number;
4
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
10 1
20 2
30 3
40 4
50 5
60 6
70 7
80 8
90 9
100 10
10 rows selected.
直方图有时对于CBO非常重要,特别是对于有字段数据非常倾斜的表,做直方图分析尤为重要。 可以用dbms_stats包来分析。 默认情况下,dbms_stats 包会对所有的列做直方图分析。
如果一个列上的数据有比较严重的倾斜,对这个列做直方图是必要的,但是,Oracle 对数据分析是需要消耗资源的,特别是对于一些很大的段对象,分析的时间尤其长。对于OLAP系统,可能需要几个小时才能完成。
所以做不做分析就需要DBA 权衡好了。 但有一点要注意, 不要在生产环境中随便修改分析方案,除非你有十足的把握。 否则可能导致非常严重的后果。
通常情况下当BUCTET < 表的NUM_DISTINCT值得到的是HEIGHT BALANCED(高度平衡)直方图,而当BUCTET = 表的NUM_DISTINCT值的时候得到的是FREQUENCY(频率)直方图。
由于满足BUCTET = 表的NUM_DISTINCT值概率较低,所以在Oracle中生成的直方图大部分是HEIGHT BALANCED(高度平衡)直方图.