2017-02-17 10 views
4

この質問は何百回も尋ねられましたが、残念なことに、これらの回答のどれも助けられませんでした。巨大なMySQLのinnoDBテーブルからレコードを削除する

records+140kk rows/+24GBextra+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

+0

最初のクエリでORDER BY idが必要ですか?それなしで試してみてください。 – Mihai

+0

これは、レプリケーションの問題を回避するために必要です。それがASC(デフォルトの順序)である限り、違いはありません。 – user2693017

+0

AFAIK 'ORDER BY id 'は、WHERE句の範囲チェックの後にインデックスを使用できません。 ORDER BYとLIMITなしで試しましたか? –

答えて

1

は、それが効率的に大きなテーブルから行の多くを削除するさまざまな方法について説明しhttp://mysql.rjweb.org/doc.php/deletebig

を参照してください。

おそらく最も効果的なのはPRIMARY KEY(それがありますか?)に基づいてテーブルを歩き回り、そのチャンク内のどの行が基準に一致していても削除します。これは効率的である

理由は、それが一度に100行、たとえば、見ていることである彼らと連携し、だけにして、次の100行に移動します。対照的に、LIMITと無制限のWHERE句を使用すると、同じ行を何度も何度もスキャンする必要があります。

あなたはJOINと述べました。それがどれほどコストがかかっているかによって、100が良い制限になることがあります。 JOINが面倒ではない場合は、おそらく1000がうまくいくでしょう。

これが定期的な作業である場合は、を使用することを検討してください。DROP PARTITIONを使用すると、即座にその行為を行うことができます。

+0

これはどのような構文ですか?私はプロシージャでそれを動作させることができません。 – user2693017

+0

擬似コード。使用している言語に変換する必要があります。 (私はPHPやPerlよりも不器用なので、ストアドプロシージャを避ける傾向があります)あなたはどの言語を書いていましたか? –

+0

このデータベースの元のアプリはjavaです。しかし、nodejs/phpやbash/perlスクリプトを好むだろう。どんな勧告? – user2693017

関連する問題