2017-04-22 97 views
0

我有一個包含3億條記錄的表(表A),我想根據某些條件執行數據保留活動。所以我想刪除大約200M表中的記錄。根據條件從非常大的表中刪除舊記錄

關於性能,我計劃創建一個新表(Table-B),其中包含Table-A中最早的10M記錄。然後,我可以從Table-B中選擇符合條件的記錄,並將其從表A中刪除。

從表A中提取10M記錄並使用SQL Loader加載到表B中需要約5小時。

我已經創建了索引,並且在適用的地方使用了並行32。

我想知道的是,

  • 有沒有更好的辦法從表-A提取和將其加載表-B。
  • 除了創建一個臨時表(Table-B)之外,還有其他更好的方法嗎?

DBMS:Oracle 10g,PL/SQL和Shell。

謝謝。

+3

這兩個表都在同一個數據庫中嗎?如果是的話,您是否使用SQL Loader來加載乳清?你不能只是'插入tableB select * from tableA'嗎?另外創建tableB作爲'no logging'來獲得更快的插入。 Google'nologging'獲取更多細節。 – Utsav

+0

我同意@Utsav,只是'插入/ * +追加* /到t2選擇*從t1哪裏'應該需要幾分鐘而不是幾個小時。這是我會更擔心的'刪除'。您是否有下一次需要分區的選項? –

+0

關於「除了創建臨時表(Table-B)之外是否還有其他更好的方法」,我不明白你的過程邏輯。表B是什麼?我的意思是,創建它的替代方法不會創建它。 –

回答

1

如果你想刪除你的表的記錄的70%,最好的方法是創建一個包含行的其餘30%的新表,刪除舊錶並將新表重命名爲舊錶的名稱。創建新表的一種可能性是創建表作爲選擇語句(CTAS),但也有可能使對運行系統的影響小得多,例如,可以使用物化視圖來選擇剩餘的數據並將物化視圖轉換爲表格。方法的細節取決於要求。 這個讀寫操作要比刪除舊錶的行更有效率。

如果刪除舊錶的行,則可能需要重新組織舊錶,這也將最終寫入剩餘的30%的數據。

-1

也許更好的做法是表A的劃分,但如果沒有,你可以嘗試快速而簡單:

declare 
    i pls_integer :=0 ; 
begin 
    for r in 
    ( -- select what you want to move to second table 
     SELECT 
      rowid as rid, 
      col1, 
      col2, 
      col3 
     FROM 
      table_a t 
     WHERE 
      t.col < SYSDATE - 30 --- or other criteria 
    ) 
    loop 
     insert /*+ append */ into table_b values (r.col1, r.col2, r.col3); -- insert it to second table 
     delete from table_a where rowid = r.rid; -- and delete it 
     if i < 500 -- check your best commit interval 
     then 
      i:=i+1; 
     else 
      commit; 
      i:=0; 
     end if;  
    end loop; 
    commit; 
end; 

在上面的例子中,你會在小500個交易移動你的記錄。你可以使用集合和批量插入來優化它,但我想保留簡單的代碼。

+0

-1這不是一個好建議。這將把負載的持續時間從5小時擴大到更多的小時。正如其他人已經說過的:拳頭考慮是否真的有必要使用表B,其次如果有必要,那麼使用'插入追加',也許nologging。你的方法沒有考慮到這一點,但增加了刪除數據的時間。 append-hint對插入值語句沒有影響,並且不斷在pl/sql和sql上下文之間切換會使這種方法更加緩慢。 – miracle173

+0

再加上'insert * values'語句的'/ * + append_values * /',並且只在11.2中添加,而OP仍然在10g上。在那個循環中好像有一個'commit'。 –

0

使用ROWID最好的使用,但內聯光標可以幫助ü更 插入到表中的值(SELECT * FROM表B,其中=標準),然後截斷表一

0
  • 有沒有更好的方法來提取從表-A並加載它?您可以使用並行CTAS - 創建table-b作爲table-a中的選擇。您可以一步使用壓縮和並行查詢。

  • 表-B。有沒有更好的方法,而不是創建一個臨時表
    表(表B)?更好的辦法是表的分區一個

0

按照您的標準對錶格進行分區可能是一個選項。

考慮標準是月的情況。所有1月份的數據都屬於Jan分區。所有2月份的數據都屬於2月份的分區...

然後,當需要刪除所有舊的一月份數據時,您只需刪除該分區即可。