MySQL - 刪大量資料效能調整
這次要刪除舊有不需要用到的資料,
在原有的幾百萬筆資料,刪除30萬筆資料。靠的是某個欄位的Id值。
使用過不同的方式刪資料,
第一個方式:
delete from TableA where FK_ID in (select ID from Table B);
超級慢,也不知道慢在哪?而且卡住,無法確認行蹤。
後來,發現,因為TableA 資料欄位很多,加上 索引數量龐大,所會導致刪資料很慢,外加,一口氣刪30萬筆的資料,事實關聯的資料可能超過300萬筆,所以可能會等到瘋掉。
改採用第二個方式,試試。
第二個方式:
將TableB ID值倒出來變csv,然後透過取代,變成delete from TableA where FK_ID = ID; 30萬行。
再ssh到linux使用 mysql -uroot -p database < delete.sql;
發現,更慢,雖然不用等那一個長串的SQL,等速度慢到吐血,
我後來實測使用delete from TableA where FK_ID in (ID1,ID2,ID3)
1筆0.06sec,2筆0.15sec,3筆0.22sec,實測50測也差不多0.22sec
發現,in其實不會慢,只是不能in太多,
另外,雖然匯檔使用整個檔案,但實際,mysql可能認知的是30萬行指令,所以可能來來回回會是30萬條來回的連線。
反而不會快到哪,而且每個都以0.15~0.22sec速度,不如一口氣刪N行算了。所以就改方法三
方法三:
使用Java撰寫,單一連線,一口氣撈1000筆,並delete from in 1000筆的方式處理。
速度快很多,我刪30萬筆關聯資料(可能超過百萬以上資料)花費1845507毫秒。
約30.75分鐘。
這還有包含先刪掉一堆跟刪除無法有索引,日後再加回就好。
發現要做這種事,先從未上線的Table開始進行處理,刪除再切換成上線,或許會避免卡lock
覺得要研究,有什麼很好的刪除方式,
但發現我在本機匯檔速度相檔的快速。(莫非跟我SSD的主硬碟有關?)
或許刪除沒這麼容易,但大量新增就沒這麼慢,不過700萬筆資料也是要花一個半到兩個小時。用insert into tableA () select * from tableB
在想,用insert into A() select * form B這樣的方式,可能由於資料龐大,佔用了記憶體,反而不會快
反而我每200~1000筆讀一次,寫進檔案,再由匯檔指令送入,反而更快。
可能使用檔案指令只是送出,並沒 select 的動作,反而花的時間比較少
最後總結:
1. delete from table in 的數量過多,會慢
2.索引過多會慢
3.匯檔,檔案裡的資料一筆一筆刪除數量太多,也會慢
4.刪除的欄位個數與長度過多,也會慢
5.關聯的筆數多,也會慢。
慢到,搞到我快吐血。