分區(qū)表部分分區(qū)不可用導致統(tǒng)計信息收集失效
一個客戶碰到的具體需求,分區(qū)表中有些分區(qū)所在的表空間被OFFLINE,tb導致在刪除統(tǒng)計信息時報錯。
下面通過例子來說明這個問題:
SQL> create table t_part_read (id number)
2 partition by range (id)
3 (partition p1 values less than (10) tablespace ts1,
4 partition p2 values less than (20) tablespace ts2,
5 partition pmax values less than (maxvalue) tablespace users);
Table created.
SQL> insert into t_part_read select rownum from tab;
54 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user, 'T_PART_READ')
PL/SQL procedure successfully completed.
SQL> alter tablespace ts1 read only;
Tablespace altered.
SQL> exec dbms_stats.gather_table_stats(user, 'T_PART_READ')
PL/SQL procedure successfully completed.
SQL> alter tablespace ts1 offline;
Tablespace altered.
SQL> exec dbms_stats.gather_table_stats(user, 'T_PART_READ')
BEGIN dbms_stats.gather_table_stats(user, 'T_PART_READ'); END;
*
ERROR at line 1:
ORA-00376: file 6 cannot be read at this time
ORA-01110: data file 6: '/u01/app/oracle/oradata/ORCL/datafile/o1_mf_ts1_7w8l5fz1_.dbf'
ORA-06512: at "SYS.DBMS_STATS", line 23829
ORA-06512: at "SYS.DBMS_STATS", line 23880
ORA-06512: at line 1
如果將表空間只讀,并不會影響到表空間上的表或分區(qū)的統(tǒng)計信息的收集,因為收集過程只是讀取,而收集的結(jié)果信息是寫到SYSTEM表空間的。
但是如果分區(qū)所在的表空間處于OFFLINE狀態(tài),那么在統(tǒng)計信息收集的過程中就會報錯。
有一個很簡單的方法可以解決這個問題,就是將被OFFLINE影響的分區(qū)的統(tǒng)計信息鎖定,這樣Oracle在收集統(tǒng)計信息時就會跳過鎖定的分區(qū),通過這個辦法就可以避免統(tǒng)計信息收集過程中的報錯:
SQL> exec dbms_stats.lock_partition_stats(user, 'T_PART_READ', 'P1')
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user, 'T_PART_READ')
BEGIN dbms_stats.gather_table_stats(user, 'T_PART_READ'); END;
*
ERROR at line 1:
ORA-00376: file 6 cannot be read at this time
ORA-01110: data file 6: '/u01/app/oracle/oradata/ORCL/datafile/o1_mf_ts1_7w8l5fz1_.dbf'
ORA-06512: at "SYS.DBMS_STATS", line 23829
ORA-06512: at "SYS.DBMS_STATS", line 23880
ORA-06512: at line 1
SQL> exec dbms_stats.gather_table_stats(user, 'T_PART_READ', granularity => 'PARTITION')
PL/SQL procedure successfully completed.
即使鎖定分區(qū)后,嘗試收集統(tǒng)計信息仍然報錯,這是因為Oracle默認除了要收集分區(qū)上的統(tǒng)計信息以外,還要收集表級的統(tǒng)計信息,而這就會造成被OFFLINE影響的分區(qū)也要被讀取。
解決方法就是在收集統(tǒng)計信息的時候指定收集的粒度是分區(qū),不收集表上的GLOBAL信息。