㈠ 先看两个来自生产环境的真实案例:
㈡ 原理:
Oracle 在对于 varchar等字符型字段收集统计信息时,并不会对每个值都进行精确的统计
而是,对值进行substr(,32)。一般来讲,这种方式没有什么问题
但是,如果恰巧列中存储的数据,前32bytes相同,那么,Oracle 的统计就会与实际情况不符
㈢ 测试:
hr@ORCL> drop table t purge; Table dropped. hr@ORCL> create table t (id number,name varchar2(300)); Table created. hr@ORCL> create index idx_t on t (name); Index created. hr@ORCL> insert into t select rownum,lpad(\'a\',6,\'a\')||to_char(rownum) from dba_objects; 50322 rows created. hr@ORCL> commit; Commit complete. hr@ORCL> exec dbms_stats.gather_table_stats(user,\'T\',null,null,method_opt=>\'for columns size 254 name\',cascade=>true); PL/SQL procedure successfully completed. hr@ORCL> 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 aaaaaa46556 NAME aaaaaa46734 NAME aaaaaa46912 NAME aaaaaa47090 hr@ORCL> truncate table t; Table truncated. hr@ORCL> insert into t select rownum,lpad(\'a\',31,\'a\')||to_char(rownum) from dba_objects; 50322 rows created. hr@ORCL> exec dbms_stats.gather_table_stats(user,\'T\',null,null,method_opt=>\'for columns size 254 name\',cascade=>true); PL/SQL procedure successfully completed. hr@ORCL> 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 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1 NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2 NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 NAME aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 hr@ORCL> truncate table t; Table truncated. hr@ORCL> insert into t select rownum,lpad(\'a\',32,\'a\')||to_char(rownum) from dba_objects; 50322 rows created. hr@ORCL> exec dbms_stats.gather_table_stats(user,\'T\',null,null,method_opt=>\'for columns size 254 name\',cascade=>true); PL/SQL procedure successfully completed. hr@ORCL> 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 ----- -------------------------------------------------- ID ID NAME
㈣ 解决方案:
删除索引列的直方图
例子:
SQL> begin
dbms_stats.gather_table_stats(ownname => \'HR\',
tabname => \'T\' ,
estimate_percent => null ,
method_opt => \'for columns SIZE 1 name\' ,
cascade => true);
end;
/来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26515977/viewspace-1208097/ ,如需转载,请注明出处,否则将追究法律责任。