2016-12-03 45 views
3

我有一個PL/SQL腳本,循環人(~4百萬)的記錄和執行多個更新(〜100)和一個刪除語句(所有這些更新和刪除在不同的表)。我面臨的問題是,一個刪除語句本身佔用大約一半的運行時間。我明白,當你執行刪除語句時,它需要更新索引,但我覺得它很荒謬。我目前正在使用dbms_parallel_execute使用一個線程測試此腳本,但我計劃對此腳本進行多線程處理。多個小刪除

我執行類似以下的查詢:

DELETE FROM table1 t1 
WHERE (t1.key1, t1.key2) IN (SELECT t2.key1, t2.key2 
           FROM table2 t2 
           WHERE t2.parm1 = 1234 
           AND t2.parm2 = 5678). 

以下事實:

  • 表2(約30萬條記錄)是〜小於表1大10倍(約3萬條記錄) 。
  • 有上表1主鍵(KEY1,KEY2)
  • 有對錶2的主鍵(KEY1,KEY2)
  • 有對錶2的索引(PARM1,parm2)
  • 我已禁用在引用table2(key1,key2)的table1(key1,key2)上的外鍵約束
  • 對table1沒有其他約束,但對table2有更多約束。

  • 上table1的所有觸發器已被禁用

  • 此查詢的解釋計劃來了一個成本比很多我的更新語句的較低(但我知道這並不佔太大)。

解釋計劃輸出:

OPERATION       OPTIONS                        OBJECT_INSTANCE        OBJECT_TYPE       OPTIMIZER                       SEARCH_COLUMNS        ID           PARENT_ID         DEPTH          POSITION          COST           CARDINALITY         BYTES          CPU_COST          IO_COST          TIME           
------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- ------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- 
DELETE STATEMENT                                                   ALL_ROWS                                              0                       0           5           5           1           36          38043           5           1 
DELETE                                                                                                     1           0           1           1                                                                    
NESTED LOOPS                                                                                                    2           1           2           1           5           1           36          38043           5           1 
TABLE ACCESS       BY INDEX ROWID                                 2 TABLE        ANALYZED                                              3           2           3           1           4           1           25          29022           4           1 
INDEX        RANGE SCAN                                  INDEX        ANALYZED                                  1           4           3           4           1           3           1                      21564           3           1 
INDEX        UNIQUE SCAN                                  INDEX (UNIQUE)      ANALYZED                                  2           5           2           3           2           1           1           11           9021           1           1 

我在想,如果有什麼辦法讓這個刪除走得更快。我試圖做一個bulk delete,但似乎並沒有改善運行時間。如果有任何方法可以執行所有的刪除操作,然後更新索引,我懷疑它會運行得更快。很顯然,從select中創建表格已經不在圖片之中,因爲我正在從另一個表中循環記錄(並通過多個條件運行)來執行刪除操作。

+0

是你的表由任何機會索引組織?嘗試'從SELECT_TABLES SELECT IOT_TYPE WHERE TABLE_NAME ='MYTABLENAME''。如果結果不是NULL,則按索引組織。 –

+0

兩個表上的結果都是NULL。 – Mocking

+1

請保留解釋輸出的格式。縮進對分析它很重要。 –

回答

0

您的每個刪除調用都在30m記錄上運行表2中的查詢,這絕對會降低性能,並且還可能會產生鎖定問題,這又會降低查詢速度。

我建議移出從table2中選擇數據的內嵌查詢。表2應該推動刪除並刪除候選人記錄。它可以作爲遊標運行或將此數據放置在臨時表中。讓刪除在500,1000的塊中執行,然後進行提交。這個塊可以根據結果進行優化。在刪除

索引更新不是冗餘的,如果這個過程是在非工作時間運行,可以禁用索引,並再次重新..

0

我是這麼認爲的,如果外部查詢是「小」和內查詢是「大」 - 一個地方可能是相當有效的。

嘗試where存在子句而不是in子句,然後檢查解釋計劃和性能。

DELETE FROM table1 t1 
WHERE 
Exists (select 1 
    FROM table2 t2 
    WHERE t2.parm1 = 1234 
AND t2.parm2 = 5678 
AND t2.key1 = t1.key1 
AND t2.key2 = t1.key2 
)