Oracle刪除大表並回收空間的過程

近日在查詢某項日誌的時候,發現查詢非常緩慢,根據以往的經驗這是由於某個日誌表過大引起的,爲了加快查詢,決定將大部分的歷史數據遷移到另外一個表中,本文主要記錄刪除這個大表的過程,就解決問題而言還有很多方法,但是本文側重點在於如何處理大數據量刪除的操作,及其善後工作。

首先看看我們要做數據遷移的表所佔的空間:

SQL> select segment_name , bytes/1048576 MB
 2 from user_segments
 3 order by bytes
 4 /
SEGMENT_NAME MB
-------------------------------------------------- ----------
TAB_NODE_PARAM .375
SYS_LOB0000053047C00004$$ .4375
PK_TAB_FLOW_HIS 1
PK_TAB_NODE_HIS 2
TAB_TASK_HIS 2
TAB_FLOW_HIS 4
TAB_NODE_HIS 17
PK_TAB_APPEXCHANGE_LOG 152
TAB_APPEXCHANGE_LOG 768看看歷史數據大概所佔的空間比例:

SQL> select count(*) from tab_appexchange_log
 2 where receive_time >= to_date('2009-01-01','yyyy-mm-dd')
 3 union all
 4 select count(*) from tab_appexchange_log
 5 where receive_time < to_date('2009-01-01','yyyy-mm-dd')
SQL> /
 COUNT(*)
----------
 1584298
 4037710從結果來看,的確存在很多歷史數據,我們將 2009 年之前的數據遷移到別的表中。

SQL> create table tab_appexchange_log_20090101
 2 as
 3 select * from tab_appexchange_log
 4 where receive_time < to_date('2009-01-01','yyyy-mm-dd')
SQL> /
Table created.
SQL> select count(*) from tab_appexchange_log_20090101
 2 /
 COUNT(*)
----------
 4037710數據已經遷移一份到新的表裏面了,可以刪除原表中的舊數據了。

SQL> delete tab_appexchange_log where receive_time < to_date('2009-01-01','yyyy-mm-dd')
 2 /
delete tab_appexchange_log where receive_time < to_date('2009-01-01','yyyy-mm-dd')
 *
ERROR at line 1:
ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS2'這裏出現了一個 ORA-30036的錯誤,大概意思是undo表空間不足,看來是要刪除的數據太多了,於是考慮化整爲零,刪一點,commit一下。

SQL> delete tab_appexchange_log where receive_time < to_date('2007-01-01','yyyy-mm-dd')
 2 /
0 rows deleted.
SQL> delete tab_appexchange_log where receive_time < to_date('2008-01-01','yyyy-mm-dd')
 2 /
1586227 rows deleted.
SQL> commit;
Commit complete.
SQL> delete tab_appexchange_log where receive_time < to_date('2008-06-01','yyyy-mm-dd')
 2 /
813019 rows deleted.
SQL> commit;
Commit complete.
SQL> delete tab_appexchange_log where receive_time < to_date('2009-01-01','yyyy-mm-dd')
 2 /
1638464 rows deleted.
SQL> commit;
Commit complete.可以預知,現在表裏面的數據應該只有 15***** 條,以下證實了這個想法。

SQL> select count(*) from tab_appexchange_log
 2 /
 COUNT(*)
----------
 1584522我們再看看錶佔用空間的情況:

SQL> select segment_name , bytes/1048576 MB
 2 from user_segments
 3 order by bytes asc;
SEGMENT_NAME MB
-------------------------------------------------- ----------
TAB_NODE_PARAM .375
SYS_LOB0000053047C00004$$ .4375
PK_TAB_FLOW_HIS 1
PK_TAB_NODE_HIS 2
TAB_TASK_HIS 2
TAB_FLOW_HIS 4
TAB_NODE_HIS 17
PK_TAB_APPEXCHANGE_LOG 152
TAB_APPEXCHANGE_LOG_20090101 552
TAB_APPEXCHANGE_LOG 768看來原表所佔的空間還沒有釋放,這個涉及一個HWM的說法,還有可以觀察到在TAB_APPEXCHANGE_LOG上面的一個索引 PK_TAB_APPEXCHANGE_LOG 空間沒有回收。

我們回過頭來看看剛纔的操作對undo表空間產生的壓力:

TO_CHAR(BEGIN_TIME, TO_CHAR(END_TIME,'Y UNDOBLKS
------------------- ------------------- ----------
2009-06-30 13:39:32 2009-06-30 13:46:35 96164
2009-06-30 13:29:32 2009-06-30 13:39:32 89316
2009-06-30 13:19:32 2009-06-30 13:29:32 209885
2009-06-30 13:09:32 2009-06-30 13:19:32 105
2009-06-30 12:59:32 2009-06-30 13:09:32 125
2009-06-30 12:49:32 2009-06-30 12:59:32 74
2009-06-30 12:39:32 2009-06-30 12:49:32 80
2009-06-30 12:29:32 2009-06-30 12:39:32 72
2009-06-30 12:19:32 2009-06-30 12:29:32 76
2009-06-30 12:09:32 2009-06-30 12:19:32 89
2009-06-30 11:59:32 2009-06-30 12:09:32 126呵呵,剛纔DML的操作對undo表空間產生的壓力還是非常可觀的。

我們開始回收表所佔的空間:

SQL> alter table TAB_APPEXCHANGE_LOG enable row movement;
Table altered.
SQL> alter table TAB_APPEXCHANGE_LOG shrink space;
Table altered.由於這麼大規模的刪除,會導致很多索引中存在很多標記爲刪除的節點,佔地方還不能發揮作用,因此重建索引將這些無用節點清理出去纔是上策。

SQL> analyze index PK_TAB_APPEXCHANGE_LOG validate structure;
Index analyzed.
SQL> select height, name , LF_ROWS_LEN,LF_ROWS,DEL_LF_ROWS,DEL_LF_ROWS_LEN from index_stats;
 HEIGHT NAME LF_ROWS_LEN LF_ROWS DEL_LF_ROWS DEL_LF_ROWS_LEN
---------- ------------------------------ ----------- ---------- ----------- ---------------
 3 PK_TAB_APPEXCHANGE_LOG 88905533 5621608 4036429 63558680
SQL> alter index PK_TAB_APPEXCHANGE_LOG rebuild online;
Index altered.
SQL> analyze index PK_TAB_APPEXCHANGE_LOG validate structure;
Index analyzed.
SQL> select height, name , LF_ROWS_LEN,LF_ROWS,DEL_LF_ROWS,DEL_LF_ROWS_LEN from index_stats;
 HEIGHT NAME LF_ROWS_LEN LF_ROWS DEL_LF_ROWS DEL_LF_ROWS_LEN
---------- ------------------------------ ----------- ---------- ----------- ---------------
 3 PK_TAB_APPEXCHANGE_LOG 25347109 1585195 0 0如果現在我們再查一下索引所佔的空間的話,會發現所佔空間是沒有減少的,和表一樣,同樣也是需要收縮一下空間。

SQL> alter index PK_TAB_APPEXCHANGE_LOG shrink space;
Index altered.
SQL> select segment_name , bytes/1048576 MB
 2 from user_segments
 3 order by bytes
 4 /
SEGMENT_NAME MB
-------------------------------------------------- ----------
TAB_NODE_PARAM .375
SYS_LOB0000053047C00004$$ .4375
PK_TAB_FLOW_HIS 1
TAB_TASK_HIS 2
PK_TAB_NODE_HIS 2
TAB_FLOW_HIS 4
TAB_NODE_HIS 17
PK_TAB_APPEXCHANGE_LOG 28.1875
TAB_APPEXCHANGE_LOG 220.8125
TAB_APPEXCHANGE_LOG_20090101 552自此一次刪除大表的操作完成,回顧一下,主要有以下幾點:

1。分批刪除數據,按批次提交。

2。回收表所佔的空間。

3。處理由於表收縮所導致的索引失效問題。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/wawayu_0/archive/2010/03/19/5395795.aspx

發佈了23 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章