2009-11-16 104 views
1

所以基本上這裏是我想要做的事情:我有一個帳戶表,我有一個acct_id列表:(3,24,515,6326,17),假設我在表中有大約10萬個帳戶,除了我的給定列表中的account_id之外,刪除所有其他行的最有效方法是什麼?刪除給定列表中除行號以外的其他所有行

我想出了這樣的:

delete from account where acct_id is not in (3, 24, 515, 6326, 17); 

我聽到這個查詢是緩慢的,因爲它是遞歸或東西。考慮我有的行數,那就是很慢。有什麼更好的方法來做到這一點?

+0

你有表關係 - 從其他表的外鍵到這個嗎? 您(計劃)在該表上有多少個索引? 這些可以顯着地改變答案:即,刪除表可能不是選項,或者簡單的DELETE性能與棘手的方式相同。 知道你在優化:它可能不會被破壞。 – 2009-11-16 23:44:42

+0

@fei我知道這個問題很老,但我可以知道你爲什麼或在哪裏聽說你的查詢很慢? – 2016-07-06 07:59:15

回答

4
 
delete from table 
where not acct_id in (3, 24, 515, 6326, etc.); 

根據數據庫的風格,索引,分佈與否等等,這可能是很多工作。這完全日誌數據庫,甚至還可以有效的替代方法是:

 
create table2 temp as /* create new table from the rows to keep */ 
    select * 
    from table 
    where acct_id in (3, 24, 515, 6326, etc.); 
drop table;   /* discard table */ 
create table as  /* copy new table to rename */ 
    select * from table2; 
drop table2;   /* get rid of temporary table */ 
+1

,這似乎與我提出的解決方案几乎相同......請謹慎解釋一下這對大量數據有效嗎? – fei 2009-11-16 23:28:11

+0

我在編寫答案時沒有看到SQL語句。你以後補充了嗎? – wallyk 2009-11-16 23:32:26

+0

我沒有把它放在代碼標籤中。但你提出的替代方案似乎很有前景。謝謝。 – fei 2009-11-16 23:37:44

0

您的查詢似乎沒什麼問題,但如果你想優化你的查詢看一看Explain

0

如果你有一個關於acct_id的索引,我看不出爲什麼你的查詢應該很慢。 據我所知

in (3, 24, 515, 6326, 17) 

僅僅是

acct_id != 3 AND acct_id != 24 ... 

語法糖應該是足夠快。

0

不是特定於MySQL,但通常刪除相對較貴,因爲它們需要引擎執行一堆選擇,以確保它正在刪除正確的記錄以及實際的刪除。您還可以結束添加到事務日誌中的大量事務(當然取決於引擎和設置)。

如果你只有你想保留一小部分的記錄,並大集要扔出去,那麼你可以通過作弊得到很多快速的性能...

你複製你想要的記錄保留並刪除或截斷表,然後添加「保持者」回來。

0

我的解決方案是避免DELETE並使用TRUNCATE表,因爲當您刪除數據庫時會執行兩個操作。刪除並將記錄寫入回滾段。

當然,這意味着在截斷時沒有回滾。

-- copy the few records into a temp table 
select into temp 
select * from account 
where acct_id in (3, 24, 515, 6326, 17); 

-- truncate is super fast 
truncate table account; 

-- put back the few records 
insert into account select * from temp; 

drop table temp; 
相關問題