2010-03-16 82 views
2

我有一個Oracle SQL查詢作爲存儲過程的一部分:SQL優化:刪除花費很長的時間

DELETE FROM item i 
WHERE NOT EXISTS (SELECT 1 FROM item_queue q WHERE q.n=i.n) 
AND NOT EXISTS (SELECT 1 FROM tool_queue t WHERE t.n=i.n); 

有關臺A位:

  • 項目包含有大約10K行在n列索引
  • item_queue含有約1mil的行也具有索引n個列
  • tool_queue含有約5密耳的行索引以及

我想知道,如果查詢/子查詢可以以某種方式優化,使其運行速度更快,我想刪除普遍較快

+1

請重新格式化您的代碼,以便它不是在滾動窗格。 – Timothy 2010-03-16 16:03:26

回答

0

嘗試使用SELECT而不是刪除看到的是DELETE操作,真正的瓶頸

4

將您的刪除轉爲選擇,然後您可以檢查和優化查詢部分。

否則注意 - 刪除不是最快的事情。很多事情發生在刪除。

OTOH我認真思考....問題是兩個子查詢。查詢計劃是什麼樣的?

1

儘量避免子選擇在您奎雷斯和使用INNER JOIN代替

+0

除INNER JOIN不起作用外。如果你在'item'和'item_queue'和'tool_queue'之間進行內部連接,你會得到你不想刪除的'item'的一個子集。 – 2010-03-16 16:13:04

+0

不是內部連接比select語句更昂貴嗎?如果我錯了,請糾正我。 – suprasad 2010-03-16 16:46:54

+0

@Shannon Severance黃金法則「兩次TIME select一次刪除」 @ sprasad12讓有人白衣更多的經驗糾正我,但我作爲我知道,作爲子選擇和函數的事情慢得多,然後在查詢中加入 – adopilot 2010-03-16 17:17:45

0

雖然它可能沒有任何更快它會更容易,如果你沒有閱讀:

DELETE FROM item i 
WHERE n NOT IN (SELECT n FROM item_queue) 
AND n NOT IN (SELECT n FROM tool_queue) 
3

試着這麼做:

DELETE FROM item WHERE n NOT IN 
    (SELECT i.n FROM item i INNER JOIN item_queue q ON i.n = q.n 
     UNION SELECT i.n FROM item i INNER JOIN tool_queue t ON i.n = t.n) 

您的相關子查詢在您的示例中各運行10K次。此技術將運行兩個INNER JOIN查詢以獲取要刪除的「n」列表。

您可能需要搗鼓一點SQL;我不熟悉Oracle方言。

+0

語法應罰款爲Oracle,但我認爲你需要使用'或',而不是'和',因爲這既**不存在原來的檢查**。另外,使用** excplicit連接**會使其更具可讀性。 – 2010-03-16 16:16:43

+0

謝謝彼得,你是對的。我編輯了答案,將兩個查詢和UNION結果集分開,避免了進入凌亂的多表JOIN;我重新格式化爲使用INNER JOIN語法(儘管對於像我這樣的老人來說,他們同樣可讀)。 – 2010-03-16 16:27:39

+0

@Larry勒斯蒂格:我同意他們同樣可讀在這種情況下,但我懷疑有人可以夠老發現使用幾十一些*真正*條件同樣可讀;-) – 2010-03-16 16:34:44

1

請確保您對引用項目表的大型表沒有約束。在刪除的情況下,這可能會真正放緩。

1

如果不做額外的工作,你無法真正得到一個好的答案。

在SQL語句iteself之後,最重要的是對象(表格和索引在這種情況下)的統計數據是有代表性的。

然後,你真的需要看看oracle選擇的訪問路徑 - 許多方法來做到這一點。

嘗試

EXPLAIN PLAN SET STATEMENT_IS = 'SQL01' FOR 
DELETE FROM item i 
WHERE NOT EXISTS (SELECT 1 FROM item_queue q WHERE q.n=i.n) 
AND NOT EXISTS (SELECT 1 FROM tool_queue t WHERE t.n=i.n); 

然後

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); 

也許在這裏發表的結果。

當你嘗試不同的事情 - 比如重新編寫查詢,修改索引,等等,你會發現,訪問路徑的變化。

這是一個相當複雜的區域 - 你需要學習/實踐。

刪除是有很多原因慢,但一大因素是對錶的索引的維護。然而,就你而言,你說只有10k行非常小。 (順便說一下,你在這裏沒有給出時間安排,目前是需要1,10或者100秒嗎?你想達到什麼目標?)所以我會關注通過更大表格的訪問路徑。

我的第一個方法將可能是:

DELETE FROM item i 
WHERE NOT EXISTS 
(SELECT NULL 
FROM item_queue q, 
     tool_queue g 
    where q.key = g.key  -- if the tables are related 
    AND q.n=i.n) ; 

但是就像我說這裏有很多因素。