2009-08-25 54 views
23

我有一個像甲骨文刪除查詢花費過多時間

DELETE from tablename where colname = value; 

這需要相當長的時間來執行查詢。 可能是什麼原因?我有一個關於colname的索引。

+0

您可以發佈您的查詢的解釋計劃(在SQL * Plus中,運行「SET AUTOTRACE ON EXPLAIN」,然後查詢)? – 2009-08-25 10:25:43

+0

SQL> set autotrace on explain SQL>從表名刪除其中nid = 1250626; 刪除1行。執行計劃------------------------------------------------ ---------- 0 DELETE STATEMENT優化程序= ALL_ROWS(成本= 2卡= 1字節= 48)1 0刪除'tablename'2 1'PK_tablename'的INDEX(唯一掃描)(INDEX(UNIQUE) )(成本= 1卡= 1字節= 48) 這是刪除1行。最初的查詢有'> ='條件,直到20分鐘左右我纔看到完成。即使使用'=',也需要一分多鐘 – Ajay 2009-08-25 11:23:59

+0

* SELECT * FROM tablename的性能怎麼樣nid = 1250626; *? – Christian13467 2009-08-25 12:59:04

回答

30

可能有多種解釋,爲什麼您的查詢需要很長的時間:

  1. 您可以通過另一個會話(很可能)被阻止。在刪除您應該確保沒有人別的鎖定該行,如:問題SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT
  2. 有可能是一個ON DELETE TRIGGER,做更多的工作,
  3. 檢查UNINDEXED REFERENCE CONSTRAINTS指向這個表(有一個script from AskTom,這將有助於您確定是否存在這樣的未索引的外鍵)。
+0

感謝您的答覆,但不是選項1和2。 – Ajay 2009-08-25 10:09:19

+2

第三是事實上的解決方案:)。 現在它在2秒內執行! – Ajay 2009-08-25 13:09:24

+0

很樂意幫忙=)。事實上,我應該把第三點放在第一位,因爲它最有可能被忽視。 – 2009-08-25 13:32:28

4

它可能是你的表與多個表相關有一個巨大的行數。

+0

提到的未索引的外鍵。正確!這是一個巨大的父母表 – Ajay 2009-08-25 13:46:41

2

該指數有多選擇性?如果你的桌子有一百萬行,而這個值達到了十五萬,那麼你的索引就沒用了。實際上,如果實際使用它可能會比無用的更糟糕。請記住,DELETE就像一條SELECT語句:我們可以調整它的訪問路徑。

此外,刪除佔用了大量的撤消表空間,因此如果系統正在經歷大量使用,您可能會從競爭中受益。在多用戶系統中,另一個會話可能對要刪除的行有鎖定。

你有ON DELETE觸發器嗎?你有ON DELETE CASCADE外鍵約束嗎?

編輯:鑑於這一切,你說了,特別是有問題的列是主鍵,以便您正試圖刪除單行,如果花費很長的時間,它是更可能是一些其他進程或者用戶在該行上有一個鎖。有什麼東西出現在V$LOCK

+0

否關於刪除觸發器。表有超過100萬行。索引列是主鍵。沒有ON DELETE CASCADE約束。 我還有另一個超過100萬行的父表,只需要一秒左右就可以刪除一行! – Ajay 2009-08-25 10:20:06

0

您的表是否保存更多記錄?
在數據庫服務器上運行有一些遞歸程序(一些嵌套循環等)嗎?
如果數據庫服務器在不同的機器上,檢查網絡問題?

+0

服務器端沒有遞歸pgms。沒有n/w問題 – Ajay 2009-08-25 10:20:54

0

所以我只是張貼我的經驗。可能對某人有幫助。

查詢

delete from foo 
where foo_id not in ( 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

用了16秒。表foo從總數2300中刪除1700條記錄。

我按照其他答案中的說明檢查了外鍵的所有索引。這沒有幫助。

解決方案:

改變了查詢

delete from foo 
where foo_id in ( 
    select foo_id from foo 
    minus 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

我已經改變了not inin和使用minus實現正確的結果。

現在查詢在0.04秒內執行。