Oracle 统计信息的备份恢复机制

统计信息的备份恢复机制:

今天说一下统计信息的备份恢复机制.从Oracle10g开始,当收集统计信息的时候,旧的统计信息会被保留,如果因为新的统计信息而出现性能问题,旧的统计信息旧可以被恢复。

Oracle的历史统计信息保存在以下几张表中:

WRI$_OPTSTAT_TAB_HISTORY 表的统计信息
WRI$_OPTSTAT_IND_HISTORY 索引的统计信息
WRI$_OPTSTAT_HISTHEAD_HISTORY 列的统计信息
WRI$_OPTSTAT_HISTGRM_HISTORY 直方图的信息

默认情况下,统计信息将被保留31天.我们可以手动进行修改

SELECT DBMS_STATS.GET_STATS_HISTORY_RETENTION FROM DUAL;
EXECUTE DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (XX);

既然旧的统计信息会被保留,那么我们如何才可以查询到历史的统计信息.

为此,Oracle提供了dba_tab_stats_history视图,我们虽然可以从视图dba_tab_stats_history可以查询表历史收集统计信息的时间,但是该视图无法显示表的总行数,我们很难去区分,由于DBA_TAB_STATS_HISTORY来源于WRI$_OPTSTAT_TAB_HISTORY,所以我们需要结合基表WRI $_OPTSTAT_TAB_HISTORY来获取更多关于表的信息.具体查询方式如下:

历史统计信息查询语句如下(表):

  SELECT b.OWNER,
        b.OBJECT_NAME TABLE_NAME, 
        TO_CHAR(a.ANALYZETIME, 'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZETIME,
        TO_CHAR(a.SAVTIME, 'YYYY-MM-DD HH24:MI:SS') CURR_ANALYZETIME,
        a.ROWCNT
  FROM SYS.WRI$_OPTSTAT_TAB_HISTORY a, DBA_OBJECTS b
  WHERE a.OBJ# = b.OBJECT_ID
    AND b.OBJECT_NAME ='TEST'
  ORDER BY a.OBJ#, a.SAVTIME;

既然我们可以查询出来旧的统计信息,那么我们如何恢复旧的统计信息呢?
Oracle提供了DBMS_STATS包供我们使用:

EXECUTE DBMS_STATS.RESTORE_TABLE_STATS ('HR','TEST',DATE);   --恢复表的统计信息
EXECUTE DBMS_STATS.RESTORE_DATABASE_STATS(DATE);    --恢复数据库的统计信息
EXECUTE DBMS_STATS.RESTORE_DICTIONARY_STATS(DATE);  --恢复数据字典的统计信息
EXECUTE DBMS_STATS.RESTORE_FIXED_OBJECTS_STATS(DATE); --恢复固定表的统计信息
EXECUTE DBMS_STATS.RESTORE_SCHEMA_STATS('OWNER',DATE); --恢复某个用户的统计信息
EXECUTE DBMS_STATS.RESTORE_SYSTEM_STATS(DATE);       --恢复SYSTEM的统计信息

从oracle 11g开始,Oracle又增加了系统信息的备份和恢复功能,我们可以将统计信息导出存放至一张表中.并可以随时进行导入恢复.
dbms_stats.export_table_stats
dbms_stats.import_table_stats

下面通过测试,来详细说明一下两种方式恢复统计信息操作的整个流程!

1.Oracle自动保留历史统计信息机制:

模拟表的统计信息恢复流程:
创建测试表:
SQL> create table hr.hang as select * from dba_objects;
Table created.

查询该表的统计信息:
SQL>select owner, table_name, num_rows, blocks, avg_row_len
from    dba_tables
where  owner='HR'
and  table_name='HANG';
OWNER            TABLE_NAME       NUM_ROWS     BLOCKS     AVG_ROW_LEN
--------------- --------------   ----------   ----------  -----------
HR                 HANG


收集统计信息:
SQL>exec dbms_stats.gather_table_stats(ownname => 'HR',tabname => 'HANG')
PL/SQL procedure successfully completed.

SQL>exec dbms_stats.gather_table_stats(ownname => 'HR',tabname => 'HANG')
PL/SQL procedure successfully completed.
(测试明显一些,收集两次)

再次查询:
SQL>select owner, table_name, num_rows, blocks, avg_row_len
from    dba_tables
where  owner='HR'
and  table_name='HANG';
OWNER              TABLE_NAME         NUM_ROWS     BLOCKS AVG_ROW_LEN
-------------- --------------------- ---------- ---------- -----------
HR                HANG                 86954       1270          98

查询统计信息历史记录:
  SELECT b.OWNER,
        b.OBJECT_NAME TABLE_NAME, 
        TO_CHAR(a.ANALYZETIME, 'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZETIME,
        TO_CHAR(a.SAVTIME, 'YYYY-MM-DD HH24:MI:SS') CURR_ANALYZETIME,
        a.ROWCNT
  FROM SYS.WRI$_OPTSTAT_TAB_HISTORY a, DBA_OBJECTS b
  WHERE a.OBJ# = b.OBJECT_ID
    AND b.OBJECT_NAME ='HANG'
  ORDER BY a.OBJ#, a.SAVTIME;

OWNER      TABLE_NAME LAST_ANALYZETIME    CURR_ANALYZETIME        ROWCNT
---------- ---------- ------------------- ------------------- ----------
HR         HANG                           2020-12-17 21:41:16
HR         HANG       2020-12-17 21:41:16 2020-12-17 21:42:28      86954



执行插入:
SQL>insert into hr.hang select * from hr.hang;
SQL>commit;

收集统计信息:
SQL>exec dbms_stats.gather_table_stats(ownname => 'HR',tabname => 'HANG')
PL/SQL procedure successfully completed.

再次查询:
SQL>select owner, table_name, num_rows, blocks, avg_row_len
from    dba_tables
where  owner='HR'
and  table_name='HANG';
OWNER      TABLE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
---------- ---------- ---------- ---------- -----------
HR         HANG           173908       2540          98


查询统计信息历史记录:
  SELECT b.OWNER,
        b.OBJECT_NAME TABLE_NAME, 
        TO_CHAR(a.ANALYZETIME, 'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZETIME,
        TO_CHAR(a.SAVTIME, 'YYYY-MM-DD HH24:MI:SS') CURR_ANALYZETIME,
        a.ROWCNT
  FROM SYS.WRI$_OPTSTAT_TAB_HISTORY a, DBA_OBJECTS b
  WHERE a.OBJ# = b.OBJECT_ID
    AND b.OBJECT_NAME ='HANG'
  ORDER BY a.OBJ#, a.SAVTIME;
  
OWNER      TABLE_NAME LAST_ANALYZETIME    CURR_ANALYZETIME        ROWCNT
---------- ---------- ------------------- ------------------- ----------
HR         HANG                           2020-12-17 21:41:16
HR         HANG       2020-12-17 21:41:16 2020-12-17 21:42:28      86954
HR         HANG       2020-12-17 21:42:28 2020-12-17 21:43:30      86954




恢复表的统计信息至2020-12-17 21:32:31
EXECUTE 
DBMS_STATS.RESTORE_TABLE_STATS 
('HR','HANG',TO_TIMESTAMP('2020-12-17 21:42:28','YYYY-MM-DD HH24:MI:SS')); 

恢复完成后查询表的统计信息:
SQL> select owner, table_name, num_rows, blocks, avg_row_len
    from    dba_tables
    where  owner='HR'
    and  table_name='HANG';

OWNER      TABLE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
---------- ---------- ---------- ---------- -----------
HR         HANG            86954       1270          98

再次查询历史信息:
  SELECT b.OWNER,
        b.OBJECT_NAME TABLE_NAME, 
        TO_CHAR(a.ANALYZETIME, 'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZETIME,
        TO_CHAR(a.SAVTIME, 'YYYY-MM-DD HH24:MI:SS') CURR_ANALYZETIME,
        a.ROWCNT
  FROM SYS.WRI$_OPTSTAT_TAB_HISTORY a, DBA_OBJECTS b
  WHERE a.OBJ# = b.OBJECT_ID
    AND b.OBJECT_NAME ='HANG'
  ORDER BY a.OBJ#, a.SAVTIME;
OWNER      TABLE_NAME LAST_ANALYZETIME    CURR_ANALYZETIME        ROWCNT
---------- ---------- ------------------- ------------------- ----------
HR         HANG                           2020-12-17 21:47:10
HR         HANG       2020-12-17 21:47:10 2020-12-17 21:48:12      86954
HR         HANG       2020-12-17 21:48:12 2020-12-17 21:48:53      86954
HR         HANG       2020-12-17 21:48:53 2020-12-17 21:50:24     173908

恢复成功.

2.导出导入方式:

我们首先需要创建一个存放统计信息的表,之后将表的统计信息导出到存放统计信息的表中.最后可以采取导入恢复.

采用导出方式来备份恢复统计信息流程测试:
SQL> create table hr.hang as select * from dba_objects;
Table created.
收集统计信息:
SQL>exec dbms_stats.gather_table_stats(ownname => 'HR',tabname => 'HANG')
PL/SQL procedure successfully completed.

查看统计信息:
select owner, table_name, num_rows, blocks, avg_row_len
from    dba_tables
where  owner='HR'
and  table_name='HANG';
OWNER      TABLE_NAME          NUM_ROWS     BLOCKS AVG_ROW_LEN
--------- ------------------- ---------- ---------- -----------
HR            HANG               86954       1270          98

备份统计信息:
进入HR用户中,创建一个存放统计信息的表:
SQL>conn hr/hr
SQL> exec dbms_stats.create_stat_table(user,'STAT_TIMESTAMP');

将表的统计信息导出传输到STAT_TIMESTAMP表中.
SQL> exec dbms_stats.export_table_stats(user,'HANG',NULL,'STAT_TIMESTAMP');
PL/SQL procedure successfully completed.

执行插入数据并收集统计信息:
SQL> insert into hr.hang select * from hr.hang;
86958 rows created.
SQL> commit;
Commit complete.

SQL> exec dbms_stats.gather_table_stats(ownname => 'HR',tabname => 'HANG')
PL/SQL procedure successfully completed.



查看当前统计信息:
SQL> select owner, table_name, num_rows, blocks, avg_row_len
   from    dba_tables
   where  owner='HR'
   and  table_name='HANG';
OWNER      TABLE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
---------- ---------- ---------- ---------- -----------
HR         HANG           173908       2540          98

恢复统计信息:
exec dbms_stats.import_table_stats(NULL,'HANG', NULL,'STAT_TIMESTAMP');

再次查看:
select owner, table_name, num_rows, blocks, avg_row_len
from    dba_tables
where  owner='HR'
and  table_name='HANG';
OWNER        TABLE_NAME          NUM_ROWS     BLOCKS     AVG_ROW_LEN
--------- -------------------     ------      ---------- -----------
HR            HANG                86954       1270          98

恢复完成.

参考:
How to View Table Statistics History (Doc ID 761554.1)
Statistics Best Practices: How to Backup and Restore Statistics (Doc ID 464939.1)
How to Gather Optimizer Statistics on 11g (Doc ID 749227.1)
How to Restore Oracle Optimizer Statistics (Doc ID 452011.1)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值