我知道這個問題已經被問過100次了,但不幸的是這些答案都沒有幫助,因爲大多數人都有很多年的歷史,所以應該證明另一個答案是正確的。從巨大的MySQL innoDB中刪除記錄表
我有兩個表,records
與+140kk rows/+24GB
和extra
與+89kk rows/+70GB
。
每個extra
行都有一個與records
的外鍵關係,索引在兩個表之間正確設置。刪除records
級聯刪除到相關的extra
行。
我需要在生產期間清除舊記錄。 跑步DELETE FROM records WHERE WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY id LIMIT 1000;
需要無休止的(我在20分鐘後殺死它,它仍然在init
)。與SELECT
一樣,在幾毫秒內完成。
由於SELECT
是那麼快,我試着用id IN (SELECT id subquery^)
,很不幸,這並沒有改變一件事,所以我在15分鐘後殺死了它。
由於刪除單條記錄的速度很快,我結束了這項工作圍繞:
for i in `seq 1 100000`; do
mysql database -e "SELECT id FROM records WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY id LIMIT 1000;" | sed 's;/|;;g' | awk '{if(NR>1)print "DELETE FROM records WHERE id = ",$1,";" }' | mysql database;
now=$(date +"%Y/%m/%d %T")
echo "[ $now ] $i.000"
done
這是能夠處理一千記錄每秒開始,但幾個循環後下降到千次/ 10-20秒。由於我需要清除10萬行,這需要將近一個月的時間才能完成,這與清除記錄的時間大致相同,因此它永遠不會完成(尤其是因爲有多個數據庫需要這些)。
數據庫存儲在SSD Crucial_CT500MX200SSD1
上,軟件爲MariaDB 10.1
和InnoDB
引擎。 innodb_flush_log_at_trx_commit
設置爲0
以避免不必要的磁盤實用程序。
根據atop
的瓶頸是磁盤,CPU幾乎處於休眠狀態,大部分內存在系統緩存中。
結構轉儲:https://gist.github.com/Slind14/0da34e09dba91cf411db2ead5ad666ef
你是否需要第一個查詢中的ORDER BY ID?不用它就試試。 – Mihai
這是避免複製問題所必需的。只要它是ASC(默認訂單)就沒有區別。 – user2693017
AFAIK'ORDER BY id'不能在WHERE子句中使用範圍檢查後使用索引。你有沒有ORDER BY和LIMIT的嘗試? –