从10g开始,Oracle可以恢复错误的统计信息。

这篇简单介绍统计信息恢复功能。



统计信息的不准确可能导致无法产生最优的执行计划,对于大部分的情况下,最新的统计信息能反映当前系统数据的分布,从而产生最优的执行计划。但是有时候收集统计信息后造成的执行计划的改变并非一定导致性能的提升,优化器很可能找到一个新的执行计划,但是新的执行计划的运行效果不一定比以前的执行计划高,从而导致整个系统性能的下降。

对于这种情况,在9i中唯一的办法就是收集统计信息之前将原有的统计信息导出,如果出现了问题,那么利用导出的原有统计信息导入到数据字典中,覆盖新的统计信息。但是这种方法一来比较麻烦,二来必须提前做好准备,如果收集新的统计信息前没有导出原有的统计,那么就没有什么太好的办法了。

而在10g中,Oracle提供了统计信息的恢复功能,从而很好的解决了这个问题。

下面是一个最简单的工具信息恢复的例子,只是在于简单介绍这个功能:

SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR(30), TYPE VARCHAR2(30));

Table created.

SQL> INSERT INTO T      

 2  SELECT ROWNUM, OBJECT_NAME, OBJECT_TYPE

 3  FROM DBA_OBJECTS;

76299 rows created.

SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

Session altered.

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T')

PL/SQL procedure successfully completed.

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TABLES

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED

------------------------------ ---------- ---------- -------------------

T                                   76299        247 2010-10-23 07:22:31

SQL> DELETE T WHERE ROWNUM < 10000;

9999 rows deleted.

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T')

PL/SQL procedure successfully completed.

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TABLES

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED

------------------------------ ---------- ---------- -------------------

T                                   66300        247 2010-10-23 07:23:13

SQL> BEGIN

 2  DBMS_STATS.RESTORE_TABLE_STATS(

 3  USER,

 4  'T',

 5  TO_TIMESTAMP_TZ('2010-10-23 07:22:31 +08:00', 'YYYY-MM-DD HH24:MI:SS TZH:TZM'));

 6  END;

 7  /

PL/SQL procedure successfully completed.

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TABLES

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED

------------------------------ ---------- ---------- -------------------

T

SQL> SELECT TABLE_NAME, STATS_UPDATE_TIME

 2  FROM USER_TAB_STATS_HISTORY

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                     STATS_UPDATE_TIME

------------------------------ ----------------------------------------------------------

T                              23-10月-1007.22.31.154605上午+08:00

T                              23-10月-10 07.23.13.208715上午+08:00

T                              23-10月-10 07.24.40.332695上午+08:00

SQL> BEGIN

 2  DBMS_STATS.RESTORE_TABLE_STATS(

 3  USER,

 4  'T',

 5  TO_TIMESTAMP_TZ('2010-10-23 07:22:31.154605 +08:00', 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM'));

 6  END;

 7  /

PL/SQL procedure successfully completed.

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TABLES

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED

------------------------------ ---------- ---------- -------------------

T                                   76299        247 2010-10-24 07:22:31

DBMS_STATS的RESTORE_*_STATS用于恢复数据库、方案或表的统计信息,不过需要注意的是,恢复过程输入的参数是TIMESTAMP WITH TIME ZONE类型,因此如果直接根据USER_TABLES中查询的LAST_ANALYZED得到的最后收集信息的DATE类型的时间戳来进行恢复,那么得到的结果多半是错误的,检查表收集统计信息情况可以查询USER_TAB_STATS_HISTORY表,对于数据库或SCHEMA的自动收集可以查询视图DBA_OPTSTAT_OPERATIONS视图。


oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html