質問
私は巨大な MySQL (InnoDB) データベースを持っており、セッション テーブルには何百万もの行が含まれています。これらの行は、同じサーバー上で実行されている、無関係で誤動作しているクローラーによって作成されました。残念ながら、今は混乱を修正する必要があります。
しようとしたら truncate table sessions;
非常に長い時間がかかるようです(30分以上)。データは気にしません。テーブルを一刻も早く消し去りたいのです。もっと手っ取り早い方法はあるのでしょうか、それとも一晩粘るしかないのでしょうか?
解決
最も簡単な方法は、完全にテーブルを削除し、同じ定義を使用して、それを再作成するには、DROP TABLEを使用することです。あなたがテーブルの上に外部キー制約を持っていないなら、あなたはそれを行う必要があります。
あなたが5.0.3よりも大きいMySQLバージョンを使用している場合は、、これはTRUNCATEで自動的に行われます。あなたはそれがTRUNCATEはFK制約にどのように機能するかを説明し、同様のマニュアルのうち、いくつかの有用な情報を得る可能性があります。 http://dev.mysql.com/doc/refman/5.0 /en/truncate-table.htmlする
EDIT:TRUNCATEからドロップまたはDELETEと同じではありません。違いについて混乱しているものについては、上記のマニュアルのリンクをチェックしてください。 (何のFKのが存在しない場合)それ以外の場合は句ます。
なしでFROM DELETEのように機能し、それができるかのドロップと同じように動作しますTRUNCATE他のヒント
(これはGoogleの結果に高い上がったように、私はもう少し命令が便利かもしれないと思った。)
MySQLは、既存のテーブルのような空のテーブルを作成するための便利な方法があり、そして、原子の表は、コマンドの名前を変更します。一緒に、これはデータをクリアするための高速な方法はあります:
CREATE TABLE new_foo LIKE foo;
RENAME TABLE foo TO old_foo, new_foo TO foo;
DROP TABLE old_foo;
完了
あなたは、スキーマ、テーブルをドロップして再作成つかむことができませんでした?
私は、MySQLでこれを行うのを発見した最良の方法はあります:
DELETE from table_name LIMIT 1000;
または10,000(それが起こるどのくらいの速に依存します)。
すべての行が削除されるまで、ループでそれを入れてください。
このことは、実際に動作するよう試みるようにしてください。これは、いくつかの時間がかかるだろうが、それは動作します。
drop table
はそれを取り除くための最速の方法である必要があります。
あなたは「ドロップ」を使用しようとしたことがありますか?私は20ギガバイト以上のテーブルの上にそれを使用しましたし、それは常に秒で完了します。
あなただけの完全テーブルを取り除きたい場合は、なぜ単にをドロップしないのそれ?
切り捨ては通常、秒以下のオーダーで、高速です。それは30分かかった場合、あなたはおそらく、あなたが切り捨てられたテーブルを参照し、いくつかの外部キーのケースを持っていました。また、関連する問題のロックがある可能性があります。
1がテーブルを空にすることができますが、あなたはそれらのテーブルが同様にスクラブしない限り外部キー参照を削除する必要がありますように、の切り捨てが効果的に効率的である。
私たちは、これらの問題を持っていました。私たちは、Railsの2.xとCookieストアとのセッションストアとしてデータベースを使用しなくなりました。ただし、テーブルをドロップすると、まともなソリューションです。あなたは、作成/あなたのドロップを行い、その後、ログを無効に一時的に、MySQLサービスを停止することを検討セーフモードで物事を起動し、したいことがあります。完了したら、もう一度ログをオンにしてください。
私はそれはそう長く取っている理由はわかりません。しかし、おそらく名前変更を試みると、空白のテーブルを再作成します。そして、あなたはそれにかかる時間を気にせず、「余分な」テーブルをドロップすることができます。
サーリーの 答え それは素晴らしいことですが、コメントに記載されているように、戦闘中に外部キーを失います。この解決策も同様です:truncate は 1 秒以内に実行されますが、外部キーは保持されます。
重要なのは、FK チェックを無効/有効にすることです。
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
insert into NewFoo SELECT * from Foo where What_You_Want_To_Keep
truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;
詳しい回答 - 一部の行を除いてすべての行を削除します
私の問題は次のとおりです。 狂ったスクリプトのせいで、私のテーブルには 7,000,000 のジャンク行が含まれていました。このテーブルのデータの 99% を削除する必要がありました, 、これが私がコピーする必要があった理由です 守りたいもの 削除する前に tmp テーブルに保存してください。
私が保持する必要があったこれらの Foo Rows は、外部キーとインデックスを持つ他のテーブルに依存していました。
そんな感じ:
insert into NewFoo SELECT * from Foo where ID in (
SELECT distinct FooID from TableA
union SELECT distinct FooID from TableB
union SELECT distinct FooID from TableC
)
しかし、このクエリは常に 1 時間後にタイムアウトしていました。だから私は次のようにしなければなりませんでした:
CREATE TEMPORARY TABLE tmpFooIDS ENGINE=MEMORY AS (SELECT distinct FooID from TableA);
insert into tmpFooIDS SELECT distinct FooID from TableB
insert into tmpFooIDS SELECT distinct FooID from TableC
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);
私の理論では、インデックスが正しく設定されているため、NewFoo を設定する両方の方法は同じであるはずだと思いますが、実際にはそうではありませんでした。
このため、場合によっては次のようにすることができます。
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
-- Alternative way of keeping some data.
CREATE TEMPORARY TABLE tmpFooIDS ENGINE=MEMORY AS (SELECT * from Foo where What_You_Want_To_Keep);
insert into tmpFooIDS SELECT ID from Foo left join Bar where OtherStuff_You_Want_To_Keep_Using_Bar
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);
truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;