问题的起因:最近发现一张分区表:从dba_table得到的统计信息跟dba_tab_stats/dba_tab_partitions查得的信息出入很大,后来查得的原因是: 脚本里调用dbms_ddl来收集统计信息,而dbms_ddl实际上是调用analyze命令,analyze基本上不会用来收集统计信息了。我们通常是调用dbms_stats来统计的。
下面是实验证明:num_rows和last_analyzed来自dba_tables/dba_tab_stats/dba_tab_partitions
SQL> create table test( a number, b varchar2(30)) partition by hash(a) partitions 8;
Table created.
SQL> insert into test select object_id,substr(object_name,1,30) from dba_objects;
43042 rows created.
SQL> select sysdate from dual;
SYSDATE
-------------------
2010-03-10 14:59:46
SQL> exec dbms_stats.gather_table_stats('SYS','TEST',cascade=>true);
PL/SQL procedure successfully completed.
SQL> select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
SYS TEST 43042 2010-03-10 15:00:12
SQL> select owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_statistics where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST 2010-03-10 15:00:12 43042
SYS TEST SYS_P101 2010-03-10 15:00:12 5496
SYS TEST SYS_P102 2010-03-10 15:00:12 5424
SYS TEST SYS_P103 2010-03-10 15:00:12 5427
SYS TEST SYS_P104 2010-03-10 15:00:12 5363
SYS TEST SYS_P105 2010-03-10 15:00:12 5324
SYS TEST SYS_P106 2010-03-10 15:00:12 5393
SYS TEST SYS_P107 2010-03-10 15:00:12 5351
SYS TEST SYS_P108 2010-03-10 15:00:12 5264
9 rows selected.
SQL> select table_owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_partitions where table_name='TEST' and table_owner='SYS';
TABLE_OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST SYS_P101 2010-03-10 15:00:12 5496
SYS TEST SYS_P102 2010-03-10 15:00:12 5424
SYS TEST SYS_P103 2010-03-10 15:00:12 5427
SYS TEST SYS_P104 2010-03-10 15:00:12 5363
SYS TEST SYS_P105 2010-03-10 15:00:12 5324
SYS TEST SYS_P106 2010-03-10 15:00:12 5393
SYS TEST SYS_P107 2010-03-10 15:00:12 5351
SYS TEST SYS_P108 2010-03-10 15:00:12 5264
8 rows selected.
SQL> select sysdate from dual;
SYSDATE
-------------------
2010-03-10 15:00:48
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
SYS TEST 43042 2010-03-10 15:00:12
SQL> select owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_statistics where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST 2010-03-10 15:00:12 43042
SYS TEST SYS_P101 2010-03-10 15:01:16 5496
SYS TEST SYS_P102 2010-03-10 15:01:16 5424
SYS TEST SYS_P103 2010-03-10 15:01:16 5427
SYS TEST SYS_P104 2010-03-10 15:01:16 5363
SYS TEST SYS_P105 2010-03-10 15:01:16 5324
SYS TEST SYS_P106 2010-03-10 15:01:16 5393
SYS TEST SYS_P107 2010-03-10 15:01:16 5351
SYS TEST SYS_P108 2010-03-10 15:01:16 5264
9 rows selected.
SQL> select table_owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_partitions where table_name='TEST' and table_owner='SYS';
TABLE_OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST SYS_P101 2010-03-10 15:01:16 5496
SYS TEST SYS_P102 2010-03-10 15:01:16 5424
SYS TEST SYS_P103 2010-03-10 15:01:16 5427
SYS TEST SYS_P104 2010-03-10 15:01:16 5363
SYS TEST SYS_P105 2010-03-10 15:01:16 5324
SYS TEST SYS_P106 2010-03-10 15:01:16 5393
SYS TEST SYS_P107 2010-03-10 15:01:16 5351
SYS TEST SYS_P108 2010-03-10 15:01:16 5264
8 rows selected.
这里可以看到通过analyze来收集统计信息的话,dba_tables的信息是不是更新的,只会更新下面的分区表信息。
SQL> exec dbms_ddl.analyze_object('TABLE','SYS','TEST','COMPUTE');
PL/SQL procedure successfully completed.
SQL> select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
SYS TEST 43042 2010-03-10 15:00:12
SQL> select owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_statistics where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST 2010-03-10 15:00:12 43042
SYS TEST SYS_P101 2010-03-10 15:03:39 5496
SYS TEST SYS_P102 2010-03-10 15:03:39 5424
SYS TEST SYS_P103 2010-03-10 15:03:39 5427
SYS TEST SYS_P104 2010-03-10 15:03:39 5363
SYS TEST SYS_P105 2010-03-10 15:03:39 5324
SYS TEST SYS_P106 2010-03-10 15:03:39 5393
SYS TEST SYS_P107 2010-03-10 15:03:39 5351
SYS TEST SYS_P108 2010-03-10 15:03:39 5264
9 rows selected.
SQL> select table_owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_partitions where table_name='TEST' and table_owner='SYS';
TABLE_OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST SYS_P101 2010-03-10 15:03:39 5496
SYS TEST SYS_P102 2010-03-10 15:03:39 5424
SYS TEST SYS_P103 2010-03-10 15:03:39 5427
SYS TEST SYS_P104 2010-03-10 15:03:39 5363
SYS TEST SYS_P105 2010-03-10 15:03:39 5324
SYS TEST SYS_P106 2010-03-10 15:03:39 5393
SYS TEST SYS_P107 2010-03-10 15:03:39 5351
SYS TEST SYS_P108 2010-03-10 15:03:39 5264
8 rows selected.
这里也可以看到调用dbms_ddl.analyze_object也只会更新分区表里的统计信息,而不会更新dba_tables的信息。
SQL> exec dbms_stats.gather_table_stats('SYS','TEST',cascade=>true);
PL/SQL procedure successfully completed.
SQL> select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
SYS TEST 43042 2010-03-10 15:07:17
SQL> select owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_statistics where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST 2010-03-10 15:07:17 43042
SYS TEST SYS_P101 2010-03-10 15:07:17 5496
SYS TEST SYS_P102 2010-03-10 15:07:17 5424
SYS TEST SYS_P103 2010-03-10 15:07:17 5427
SYS TEST SYS_P104 2010-03-10 15:07:17 5363
SYS TEST SYS_P105 2010-03-10 15:07:17 5324
SYS TEST SYS_P106 2010-03-10 15:07:17 5393
SYS TEST SYS_P107 2010-03-10 15:07:17 5351
SYS TEST SYS_P108 2010-03-10 15:07:17 5264
9 rows selected.
SQL> select table_owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_partitions where table_name='TEST' and table_owner='SYS';
TABLE_OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST SYS_P101 2010-03-10 15:07:17 5496
SYS TEST SYS_P102 2010-03-10 15:07:17 5424
SYS TEST SYS_P103 2010-03-10 15:07:17 5427
SYS TEST SYS_P104 2010-03-10 15:07:17 5363
SYS TEST SYS_P105 2010-03-10 15:07:17 5324
SYS TEST SYS_P106 2010-03-10 15:07:17 5393
SYS TEST SYS_P107 2010-03-10 15:07:17 5351
SYS TEST SYS_P108 2010-03-10 15:07:17 5264
8 rows selected.
只有dbms_stats在更新分区表统计信息的同时,更新dba_tables.
SQL> insert into test select object_id,substr(object_name,1,30) from dba_objects;
43042 rows created.
SQL> exec dbms_ddl.analyze_object('TABLE','SYS','TEST','COMPUTE');
PL/SQL procedure successfully completed.
SQL> select owner,table_name,num_rows,last_analyzed from dba_tables where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
SYS TEST 43042 2010-03-10 15:07:17
SQL> select owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_statistics where table_name='TEST' and owner='SYS';
OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST 2010-03-10 15:07:17 43042
SYS TEST SYS_P101 2010-03-10 15:08:54 10992
SYS TEST SYS_P102 2010-03-10 15:08:54 10848
SYS TEST SYS_P103 2010-03-10 15:08:54 10854
SYS TEST SYS_P104 2010-03-10 15:08:54 10726
SYS TEST SYS_P105 2010-03-10 15:08:54 10648
SYS TEST SYS_P106 2010-03-10 15:08:54 10786
SYS TEST SYS_P107 2010-03-10 15:08:54 10702
SYS TEST SYS_P108 2010-03-10 15:08:55 10528
9 rows selected.
SQL> select table_owner,table_name,partition_name,last_analyzed,num_rows from dba_tab_partitions where table_name='TEST' and table_owner='SYS';
TABLE_OWNER TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ------------------- ----------
SYS TEST SYS_P101 2010-03-10 15:08:54 10992
SYS TEST SYS_P102 2010-03-10 15:08:54 10848
SYS TEST SYS_P103 2010-03-10 15:08:54 10854
SYS TEST SYS_P104 2010-03-10 15:08:54 10726
SYS TEST SYS_P105 2010-03-10 15:08:54 10648
SYS TEST SYS_P106 2010-03-10 15:08:54 10786
SYS TEST SYS_P107 2010-03-10 15:08:54 10702
SYS TEST SYS_P108 2010-03-10 15:08:55 10528
8 rows selected.
即使数据量出现大的变动,analyze也不会反映到dba_tables,这就再次说明用analyze来收集统计信息是存在问题的,正当途径还是用dbms_stats来收集。这个脚本也不知是哪位大佬写的。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/45188/viewspace-1031729/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/45188/viewspace-1031729/
本文探讨了在Oracle数据库中使用不同方法收集分区表统计信息的效果。通过对比analyze命令、dbms_ddl及dbms_stats包的功能,揭示了它们对dba_tables和分区表统计信息更新的不同影响。
1142

被折叠的 条评论
为什么被折叠?



