在11g中,Oracle在统计信息方面进行了进一步的增强。

这篇介绍PENDING统计信息。



在10g中,Oracle提供了恢复统计信息的方法,这使得统计信息收集后造成的问题可以通过恢复原始统计信息的方法快速解决。

在11g中,Oracle更进了一步,用户收集的统计可以设置为悬而未决的,等到统计信息验证过然后在发布到数据字典中。

SQL> SELECT * FROM V$VERSION;

BANNER

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

Oracle Database11gEnterprise Edition Release11.2.0.1.0 - 64bit Production

PL/SQL Release 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

SQL> SELECT DBMS_STATS.GET_PREFS('PUBLISH') FROM DUAL;

DBMS_STATS.GET_PREFS('PUBLISH')

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

TRUE

这个查询用于检查收集的统计信息是否即时生效,默认情况下,用DBMS_STATS包收集的统计信息会马上更新到数据字典中,并对优化器生效。

SQL> CREATE TABLE T (ID NUMBER);

表已创建。

SQL> INSERT INTO T SELECT ROWNUM FROM TAB;    

已创建24行。

SQL> COMMIT;

提交完成。

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

PL/SQL过程已成功完成。

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

会话已更改。

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                                      24          5 2010-10-28 08:04:50

这时默认的情况,如果修改全局设置,使得PENDING方式生效:

SQL> EXEC DBMS_STATS.SET_TABLE_PREFS(USER, 'T', 'PUBLISH', 'FALSE')

PL/SQL过程已成功完成。

SQL> DELETE T;

已删除24行。

SQL> INSERT INTO T SELECT ROWNUM FROM ALL_OBJECTS;

已创建69442行。

SQL> COMMIT;

提交完成。

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

PL/SQL过程已成功完成。

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                                      24          5 2010-10-28 08:04:50

可以看到,新收集的统计信息并没有覆盖数据字典中原始的统计信息,这是因为表T的全局属性被修改,此时收集的统计信息并不会马上发布,而是至于PENDING状态,可以通过查询数据字典USER_TAB_PENDING_STATS获取PENDING统计信息:

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TAB_PENDING_STATS

 3  WHERE TABLE_NAME = 'T';

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED

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

T                                   69442         54 2010-10-28 08:09:49

如果确认PENDING统计信息无误,可以调用PUBLISH_PENDING_STATS过程来发布统计信息:

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

PL/SQL过程已成功完成。

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                                   69442         54 2010-10-28 08:09:49

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, LAST_ANALYZED

 2  FROM USER_TAB_PENDING_STATS

 3  WHERE TABLE_NAME = 'T';

未选定行

如果说恢复统计信息功能给了DBA亡羊补牢的机会,那么PENDING功能就是防患于未然,而且这两个功能可以配合使用,从而将统计信息操作造成的风险降到最低。



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