セッションテーブルに数百万行の巨大なMySQL(InnoDB)データベースがあり、それらは私たちと同じサーバーで実行されている無関係で誤動作しているクローラーによって作成されました。残念ながら、私は今混乱を修正しなければなりません。
truncate table sessions;
非常に長い時間がかかるようです(30分以上)。データは気にしません。できるだけ早くテーブルを一掃したいだけです。もっと速い方法はありますか、それとも一晩で突き出さなければなりませんか?
最も簡単な方法は、DROP TABLEを使用してテーブルを完全に削除し、同じ定義を使用してテーブルを再作成することです。テーブルに外部キー制約がない場合は、それを行う必要があります。
5.0.3以降のMySQLバージョンを使用している場合、これはTRUNCATEで自動的に行われます。マニュアルからも有用な情報が得られる場合があります。TRKATEがFK制約でどのように機能するかを説明しています。 http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html
編集:TRUNCATEは、ドロップまたはDELETE FROMとは異なります。違いについて混乱している場合は、上記のマニュアルリンクを確認してください。 TRUNCATEは、可能な場合(FKがない場合)ドロップと同じように動作します。そうでない場合、where句のないDELETE FROMのように動作します。
(これは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
は、それを取り除くための最速の方法でなければなりません。
切り捨ては高速で、通常は数秒以下です。 30分かかった場合、おそらく、切り捨てるテーブルを参照している外部キーのケースがあったでしょう。関係するロックの問題もあります。
Truncateは、テーブルを空にすることができるのと同じくらい効率的ですが、これらのテーブルも同様にスクラブする必要がない限り、外部キー参照を削除する必要がある場合があります。
「ドロップ」を使用しようとしましたか? 20GBを超えるテーブルで使用しましたが、常に数秒で完了します。
テーブルを完全に削除したい場合は、単にdrop itだけではどうですか?
これらの問題がありました。データベースをRails 2.xとCookieストアでセッションストアとして使用しなくなりました。ただし、テーブルを削除することは適切なソリューションです。一時的にmysqlサービスを停止することを検討してください。ロギングを無効にし、セーフモードで起動してからドロップ/作成を行います。完了したら、再度ロギングをオンにします。
searleaの answer はニースですが、コメントに記載されているように、戦闘中に外部キーを失います。 この解決策は似ています:切り捨ては1秒以内に実行されますが、外部キーは保持します。
秘Theは、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行は、外部キーとインデックスを持つ他のテーブルに依存していました。
そんな感じ:
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;
なぜそんなに時間がかかるのか分かりません。ただし、おそらく名前を変更して、空のテーブルを再作成してください。その後、「余分な」テーブルを、どれだけ時間がかかるか心配することなく削除できます。