首页 > 数据库 > Oracle > 统计信息的32位限制
原帖在此:http://www.itpub.net/thread-1339053-1-1.html
Oracle在对于varchar等字符型字段收集统计信息时,并不会对每个值都进行精确的统计,而是,对值进行substr(,32)。一般来讲,这种方式没有什么问题,但是,如果恰巧列中存储的数据,前32bytes相同,那么,Oracle的统计就会与实际情况不符。
请看下面的例子:
[@more@]SQL*Plus: Release 11.2.0.1.0 Production on 星期五 8月 20 10:40:54 2010
Copyright (c) 1982, 2010, Oracle. All rights reserved.
SQL> conn test/test
已连接。
SQL> drop table t;
表已删除。
SQL> create table t (id integer,name varchar2(300));
表已创建。
SQL> create index t_idx on t(name);
索引已创建。
SQL> insert into t
2 select rownum,lpad('a',6,'a')||to_char(rownum) from dba_objects;
已创建64972行。
SQL> commit;
提交完成。
SQL> exec dbms_stats.gather_table_stats(user,'T',null,null,method_opt=>'for columns size 254 name',cascade=>true);
PL/SQL 过程已成功完成。
SQL> select count(*)
2 from user_tab_histograms
3 where table_name = 'T'
4 order by column_name, endpoint_Number;
COUNT(*)
----------
255 --小于32字节,没问题
SQL> col column_name format a5
SQL> col endpoint_actual_value format a50
SQL> select column_name, endpoint_actual_value
2 from user_tab_histograms
3 where table_name = 'T'
4 and rownum<5
5 order by column_name, endpoint_Number;
COLUM ENDPOINT_ACTUAL_VALUE
----- --------------------------------------------------
NAME aaaaaa57227
NAME aaaaaa57457
NAME aaaaaa57687
NAME aaaaaa57916
SQL> truncate table t;
表被截断。
SQL> insert into t
2 select rownum,lpad('a',32,'a')||to_char(rownum) from dba_objects;
已创建64972行。
SQL> commit;
提交完成。
SQL> exec dbms_stats.gather_table_stats(user,'T',null,null,method_opt=>'for colu
mns size 254 name',cascade=>true);
PL/SQL 过程已成功完成。
SQL> select column_name, endpoint_actual_value
2 from user_tab_histograms
3 where table_name = 'T'
4 order by column_name, endpoint_Number;
COLUM ENDPOINT_ACTUAL_VALUE
----- --------------------------------------------------
NAME
前32bytes相同,那么最后的桶只有1个
SQL> truncate table t;
表被截断。
SQL> insert into t
2 select rownum,lpad('a',31,'a')||to_char(rownum) from dba_objects;
已创建64972行。
SQL> exec dbms_stats.gather_table_stats(user,'T',null,null,method_opt=>'for colu
mns size 254 name',cascade=>true);
PL/SQL 过程已成功完成。
SQL> select column_name, endpoint_actual_value
2 from user_tab_histograms
3 where table_name = 'T'
4 order by column_name, endpoint_Number;
COLUM ENDPOINT_ACTUAL_VALUE
----- --------------------------------------------------
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa5
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8
NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9
已选择9行。
完全符合32bytes。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19423/viewspace-1037100/ ,如需转载,请注明出处,否则将追究法律责任。