この質問は何百回も尋ねられましたが、残念なことに、これらの回答のどれも助けられませんでした。巨大なMySQLのinnoDBテーブルからレコードを削除する
records
と+140kk rows/+24GB
とextra
と+89kk rows/+70GB
の2つのテーブルがあります。
すべてextra
の行には、records
との外部キーの関係があり、2つのテーブルの間にインデックスが正しく設定されています。 records
から削除すると、関連するextra
行に削除がカスケードされます。
製造中に古いレコードを消去する必要があります。 DELETE FROM records WHERE WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY id LIMIT 1000;
を実行すると無限になります(まだ12分後に私はそれがまだinit
だった)。 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秒に1回。私は100k行をパージする必要があるので、これは完了までに約1ヶ月かかるでしょう。これは、パージするレコードが出ている時間とほぼ同じです。したがって、これは決して終わらないでしょう(特にこれを必要とするデータベースが複数ある)。
データベースはSSD Crucial_CT500MX200SSD1
に保存され、ソフトウェアはInnoDB
エンジンのMariaDB 10.1
です。 innodb_flush_log_at_trx_commit
は、不要なディスクの使用を避けるため、0
に設定されています。
atop
によると、ボトルネックがディスクで、CPUはほとんど眠っているとMEMのほとんどは、システムキャッシュです。
構造ダンプ:https://gist.github.com/Slind14/0da34e09dba91cf411db2ead5ad666ef
最初のクエリでORDER BY idが必要ですか?それなしで試してみてください。 – Mihai
これは、レプリケーションの問題を回避するために必要です。それがASC(デフォルトの順序)である限り、違いはありません。 – user2693017
AFAIK 'ORDER BY id 'は、WHERE句の範囲チェックの後にインデックスを使用できません。 ORDER BYとLIMITなしで試しましたか? –