2013-07-31 49 views
2

我有一個包含大約1.8億條記錄和40個索引的表。夜間程序將數據加載到此表中,但由於某些業務條件,我們只能刪除數據並將數據加載到此表中。每晚程序將從源系統中爲表中現有記錄帶來新記錄或更新。我們有限的窗口,即大約6小時完成源系統的提取,執行業務轉換並最終將數據加載到此目標表中,並且準備好讓用戶在早上使用這些數據。我們面臨的問題是,從表中刪除需要很長時間,主要是由於表中的40個索引(平均每小時刪除70000個)。我做了一些挖掘在互聯網上看到下面的選項在Oracle BIG表中刪除緩慢

一)丟棄或禁用索引中刪除之前,然後重新創建索引:它加載數據到目標表的程序刪除後並加載數據需要相當執行一些更新的索引是至關重要的。由於表中的大量數據,重建1個索引需要近1.5個小時。因此,這種方法是不可行的,由於它需要重建索引的時間和由於我們要準備好這些數據爲用戶

有限的時間

B)使用批量刪除:目前該程序刪除基於ROWID並刪除記錄逐一如下

DELETE FROM <table> WHERE rowid = g_wpk_tab(ln_i);

g_wpk_tab是保存它是由通過FOR ALL循環讀取的rowid要刪除的收集和我做一箇中間媒介的提交每50000行刪除。

AskTom的湯姆說,在這個討論在這裏說,批量刪除和逐行刪除要用近的時間

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5033906925164

等量所以這不會是一個可行的選擇,以及

C)定期刪除:AskTom的湯姆建議使用定期刪除,甚至需要較長的時間可能是由於指數在這個表上的號碼

d)CTAS:這種方法是不成問題的,因爲該程序需要重新創建該表中,創建40個索引,然後與更新出發,我的索引如上所述將採取ATLEAST 1.5小時,以創建

如果你能提供任何其他建議,我會非常感激。

更新:截至目前,我們已決定採用https://stackoverflow.com/users/409172/jonearles建議的方法來存檔而不是刪除。方法是向表中添加一個標記,以將要刪除的記錄標記爲DELETE,然後在白天運行刪除程序以刪除記錄。這將確保數據在適當的時間爲用戶提供。由於用戶通過OBIEE使用,我們計劃在表上設置內容級過濾器,而不是查看存檔列,以便用戶不必知道要選擇什麼以及要忽略什麼。

+2

對於使用「所有」,你的意思是你是批量收集rowids和使用'forall' ..?你有企業版嗎?你可以分區嗎?桌子是否需要如此之大?你有沒有考慮過讓它變小?你需要40個索引嗎?如果你刪除10,它會讓你的刪除速度更快。這聽起來好像你已經把整個數據庫放在一張表中......如果你有一個小的進程每天24小時刪除一些舊的記錄會有什麼不同? – Ben

+1

你可以並行運行20個進程以加快刪除速度嗎?您可以使用DBMS_PARALLEL_EXECUTE來分割操作並輕鬆啓動20。你有沒有追溯到任何特定原因的緩慢;例如,如果整個表位於一個磁盤上,並且您有20-30個進程試圖從同一磁盤上刪除,則可能會遇到大量I/O問題。如果你有多個進程試圖從相同的塊中刪除rowid,你會得到爭用。最後,你在用什麼磁盤?它們是15年前的5rpm旋轉磁盤還是他們可愛的新型9k/TB SAN? – Ben

+0

我正在使用所有循環通過具有rowid的集合。我沒有使用批量收集。我被告知,分區成本很高,客戶無法負擔得起。該表包含公司過去4個會計年度的詳細級別的發票交易。我們正在考慮是否可以刪除一些索引。我已經開始嘗試刪除一些索引並查看性能增益。 – Shaz

回答

1

並行DMLalter session enable parallel dml;,delete /*+ parallel */ ...;,commit;。有時候很簡單。

並行DDLalter index your_index rebuild nologging compress parallel;。 NOLOGGING減少索引重建期間生成的重做量。 COMPRESS可以顯着減少非唯一索引的大小,從而顯着縮短重建時間。如果您有多個CPU或多個磁盤,則PARALLEL還可以在重建時間上產生巨大差異。如果你還沒有使用這些選項,我不會感到驚訝,如果將它們全部結合使用,可以將索引重建提高一個數量級。然後1.5 * 40/10 = 6小時。

重新評估你的索引真的需要40個索引嗎?這完全有可能,但許多索引只是因爲「索引是魔術」而創建的。確保每個索引背後都有合法的原因。這可能非常困難,很少有人記錄索引的原因。在你問周圍之前,你可能想收集一些信息。打開index monitoring查看哪些索引真的被使用。即使使用索引,也可以通過v $ sql_plan查看它是如何使用的。有可能索引用於特定語句,但另一個索引也可以起作用。

存檔而不是刪除而不是刪除,只需設置一個標誌,以標記一行作爲存檔,無效,刪除等。這將避免索引維護的直接開銷。暫時忽略行並讓其他作業稍後刪除。這樣做的一大缺點是它會影響表上的任何查詢。

升級可能不成問題,但12c有一個有趣的新功能,稱爲in-database archiving。這是完成同樣事情的更透明的方式。

+0

對於選項1,即並行DML,如果程序要在並行DML操作語句之後的任何SQL語句中使用同一個表(在此情況下爲刪除),那麼這將是一個真正的選項嗎?特別是 - 「如果事務中的任何DML語句並行修改表,則後續的串行或並行查詢或DML語句不能在該事務中再次訪問同一個表,這意味着併發修改的結果在事務處理期間無法看到。 「除非有中間承諾。 – Annjawn

+0

@Annjawn是的,並行性有很多限制和副作用。但是如果這個過程會讓數據離線,那麼通常有解決這些問題的辦法。我會爲我的步驟添加一個'commit;',因爲這幾乎總是下一步,除非出現錯誤。 –

+0

我遇到過很多次這麼多的程序,我們在這裏執行大型表上的批量DML,而這總是限制使用並行DML的問題。 'commit;'不是一個選項,因爲在提交點後程序可能會失敗,可能會使我們損壞數據,甚至難以恢復作業失敗。 – Annjawn