2011-07-07 56 views
3

我有一個相當簡單的表格,大約有一百萬行。「where in」子句的實際限制

id | my_col | other1 | other 2 | ... 

該表中有大約15k個不同的my_col值,我有一個my_col索引。我有一組7k my_col值,我需要從此表中刪除。

在SQL中做什麼更有效率的事情(我目前正在使用MySQL,但將來可能會移植到MS SQL)。

是不是a)在我的java應用程序代碼中,遍歷所有my_col值並在每個值上調用sql delete。

for (String my_colValue : listMyCol) { 
    [delete from my_table where my_col = my_colValue] 
} 

或b)使用「where in」子句構建包含所有這些值的單個SQL [large]語句?

delete from my_table where my_col in ('aaa', 'aab', 'aac', ...) 

我猜這是b),但我不確定是否在此「where in」子句中指定的7k值變得低效。

對於它的價值,我的應用服務器和數據庫服務器都託管在亞馬遜上,但在不同的層次上。

+0

請停止標記標題。你已經做了將近2年的時間了嗎? –

+0

調度7k SQL獨立查詢顯然總是最慢的「解決方案」。 –

回答

2

c)重新創建表格。

你要刪除你的一半行,所以想想吧。 儘管a)和b)可能會永遠存在,但重新創建您的桌子將會更具技巧性,但是立竿見影。

而你需要加載一個臨時表的7K值,那麼很容易:

CREATE TABLE newMyTable 
AS 
SELECT myTable.* 
FROM myTable 
    INNER JOIN myValues 
     ON myTable.my_col = myValues.my_col 

或者,如果你不能創建表,也許這將是速度不夠快:

DELETE FROM myTable t 
WHERE EXISTS 
(
    SELECT * 
    FROM myValues v 
    WHERE t.my_col = v.my_col 
) 

但是您需要牢記的唯一事情就是:您必須創建一個包含7k值的表格。

+1

遲來的接受 - 我花了一段時間來測試和驗證。性能確實優越。然而,「CREATE TABLE newMyTable AS ...」方法並沒有從myTable中取消索引,而是採用了這種方法。所以,而是我採取了兩步辦法 - 創建newMyTable作爲正常(完整的索引),然後做了一個「INSERT INTO newMyTable SELECT * FROM myTable WHERE ...」 – Kevin

1

我會與第一選擇,但我會把一切都在一個交易。通過這種方式,提交將在最後完成,而不是在每個DELETE語句之後。

索引在搜索多條記錄時變得效率低下。

2

使用WHERE IN的真正實際限制是您可以使您的SQL查詢有多大。這由MySQL的max_packet_size配置變量定義。其他任何東西都只是性能折衷。爲了找出最快的方法,基準測試仍然效果最好。