不同统计方式导致分区表的统计信息不同

本文探讨了在Oracle数据库中使用不同方法收集分区表统计信息的效果。通过对比analyze命令、dbms_ddl及dbms_stats包的功能,揭示了它们对dba_tables和分区表统计信息更新的不同影响。

问题的起因:最近发现一张分区表:从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

[@more@]

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/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值