ORACLE 關於DELETE操作的一些事


  在實際工作中,經常會遇到這樣的需求:定期對已經過期的數據進行刪除,釋放服務器資源。例如,我們定義了一個定時器任務,在凌晨2點開始執行,這個任務就是刪除1個月之前的數據,以釋放空間。

  最初的時候,我們可以這么寫:

  delete from table_name where t_time < to_date(‘2015-04-01’,’yyyy-mm-dd’)

  這個一個最簡單不過的根據條件進行刪除數據的操作。乍看之下沒有任何問題,但是當數據量十分龐大的時候,一個月就有上千萬條數據的時候,就會大量占用數據庫的資源。凌晨2點執行的語句,可能要到中午12點才能執行完畢,以至於這段時間內,查詢操作就會變得無比緩慢,平時半分鍾返回結果的查詢,此時就會變成了十幾分鍾。這顯然是不可取的。

  

  在delete操作中,sql語句首先要掃描表或者索引找到符合條件的記錄,然后把它們刪除。這個過程會消耗大量的CPU資源和產生大量的IO,同時還會產生大量的undo數據。一次性刪除10000條左右的數據,差不多要產生了10000多個數據塊讀取,將近3MB的redo日志。

  與delete相比,drop和truncate操作消耗的資源要相對小的多。同樣是刪除10000條數據,delete會產生10000多次的數據塊讀取;dro會產生1100多次的數據塊讀取;truncate則只有600多次的數據塊讀取。

 

  一般情況下,我們刪除表中數據是為了釋放空間。delete操作不能釋放空間,刪除了哪個表中的數據,騰出的空間也只能提供給哪個表使用,並不能讓給其他的對象使用。如果希望通過刪除數據騰出空間給其他對象使用,delete是不行的。

  drop和truncate操作騰出的空間則能夠提供其他對象使用。

 

   也許有人會問,drop和truncate操作消耗的系統資源和速度是比delete快,但是truncate會清空表中所有的數據,drop更是連表都一起刪除了,這樣顯然不能實現博客開始提出的定時刪除表中上個月數據的功能。這種情況下我們就要用到表分區了。

  根據時間字段t_time按照每個月一個分區的方式來創建一個范圍分區:

partition by range(t_time)

(

partition table_name_2015_1 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_2 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_3 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_4 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_5 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_6 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_7 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_8 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_9 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_10 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_11 values less than(to_date('01/01/2015','dd/mm/yyyy')),

partition table_name_2015_12 values less than(to_date('01/01/2015','dd/mm/yyyy'))

);

  這樣按照月份刪除數據的時候,我們可以:

  alter table table_name truncate partition table_name_2015_1;

  或者:

  alter table table_name drop partition table_name_2015_1;

  還有人會問,truncate刪除的數據是不會留下undo日志的,不能進行數據回滾等操作。其實在實際開發中,歷史數據一般都會移植到另外的數據庫中進行保存,這種數據庫稱作為離線數據庫或者歷史數據庫。

  只要我們在刪除表空間中數據前,先通過程序或者數據庫等操作方式將數據先備份到歷史數據庫中,在刪除表空間中的數據。

 

  一般情況下,只有大數據的情況下才會用到表分區,只有幾萬條數據或者千單位的數據的時候,使用傳統的delete操作就可以了,性能上並不會有什么太大的區別。

  文章參考了《讓ORACLE跑得更快2 基於海量數據的數據庫設計與優化》書中內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM