MYSQL 刪除百萬級數據

MYSQL 剛建立的數據庫的時候,沒有考慮數據過多會導致後續查詢的問題,也沒有建立定期刪除的存儲過程,等到發現資料過大的時候,直接刪除已經不可行了,所以不得不去嘗試其他的方式。

數據庫情況:每天有50W筆資料進去,現在累計下來已經有9000W多筆數據了,計劃只保留最後一個月的數據

1. 最簡單 ,也是最不可行的方式

delete from tablename where updatedate<'xxxx';

如果數據庫的數據在百萬級以內,這一條頂多只是慢一點,但是對待千萬級別的數據庫,即使你已經把日期欄位列爲了索引列,也不要輕易嘗試這一條,因爲在等待很久很久之後,你就會收到MYSQL的報錯,這是本人的血淚史,更不要在數據還在進來的情況下(上班時間),那樣五分鐘內,就會有連環奪命call找上你。

2. 不按時間檢索,按主鍵ID檢索

Select @maxData=max(IDColomn) from tablename where updatedate<'xxxx';
delete from tablename where IDColomn<@maxData;

改成這樣的好處是,主鍵ID欄位是int格式,按它檢索肯定比按日期或字符串格式檢索快,如果你足夠幸運碰到了一臺超級強大的硬件配置,應該也是有機會的,只是很慢很慢…,當初在數據還沒有到2000W筆的時候,我就是這樣做的,想起來了就去刪一刪,也成功了,不過等到發現9000W筆的時候,這一條就卡死了,畢竟要刪除的資料辣麼多

3. 按索引分段刪除,一步不到位,我就兩步,兩步不到位,我就三步。。。

Select @minData=min(IDColomn) from tablename;  

也可以用order by updatedate asc的方式去找到最小的那一條,記下那個minData,然後在原有基礎上加10W,舉例加完的數據爲 tmpID

delete from tablename where IDColomn<tmpID; 

選擇的這個10W也不一定,我有嘗試過10W,30W,50W,100W,它的時間並不是按照這個數據的倍數增加的,看你mysql的承受能力,可以自己嘗試,我這邊100W的時間是 13min,如果是你選10W的,的確每筆很快,2分鐘不到,但你算一下你需要這樣運行多少次。。。
在這裏插入圖片描述
4. 可以建立存儲過程,讓它自己循環去刪,但還是那句話,看你MySQL的承受能力,如果因爲它服務器掛了,就很不美好了,畢竟我曾經大半夜在保安的注視下進入公司重啓那臺服務器,還問我"這麼大半夜還進去上班嗎?"

CREATE DEFINER=`root`@`%` PROCEDURE `DeleteOverDueData`()
BEGIN
select @minData:=min(IDColomn) from tablename ;
select @maxData:=max(IDColomn) from tablename ;
while minData<maxData do
DELETE from tablename where IDColomn<@maxData limit 400000;  ## 這裏的400000 可以自己定,就是每次刪除多少筆,跟第三項一樣,畢竟不能一次全刪
call DeleteOverDueData();
end while;
END

這樣建立之後mysql只要調用這個存儲過程就好了,但是我寫完之後對單條指令做了驗證,發現前邊增加的兩步select語句運行起來其實挺慢, 所以總時間會比手動按方法3更長,我最終放棄了這個方案,選擇一下午手動操作來刪除,不想親眼見證數據刪除過程的可以試試

**最後忠告.:趁着剛刪完數據的數據庫沒那麼大的時候,趕緊建立存儲過程,定時觸發,不然又要浪費幾個週末了,下面附上存儲過程最關鍵的兩條指令 **

select @maxNum:=max(IDColomn) from  tablename  where updatedate(DataTime)<date(date_sub(now(),interval 30 day));
DELETE from tablename   where IDColomn<@maxNum;

其實明眼人一看我的這些問題,可能就會提說是不是之前的數據庫建立的時候沒有分區分表呀,或是時間沒有按datetime格式啊,等等吧,但是這種問題解決不了現在的困境啊,分區這些不是沒有嘗試過,但是因爲數據量太大,分區也是直接卡死了,所以纔不得不這樣就刪除資料了,也沒有辦法去責怪當初建數據庫的人員,誰不是在摸索中長大呢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章