大きなテーブルと一意のキー

先日、テーブルに新しいフィールドを追加するというタスクがありました。 ALTER TABLE ...そこにはなかったようです。



私はこのリクエストを夕方に実行しましたが、朝はまだ実行されていました(16時間では十分ではありませんでした:)



私はすぐに、ユニークなインデックスと元のテーブルの巨大なサイズを構築する際に問題が発生する可能性が最も高いと示唆しました。 ご存じのとおり、ALTER TABLEを使用して、サーバーは必要なデータをコピーする一時ファイルを作成します。 SHOW PROCESSLISTはこれを確認しました。



問題のより詳細な説明をします。



与えられた。 データ表があります。

タイプ-MyISAM。

テーブルには、長さが140文字のVARCHARフィールドと一意のキーがあります。

テーブルには約1億5,000万行あります。

ディスク上のボリュームは15 GBです。

テーブルに新しいフィールドを追加する必要があります。



この検索により、問題は既知であり、通常の方法は永遠に続くことが示されました。 インデックスのサイズにより、RAMでキャッシュを使用できないため、新しいテーブルを1行ずつ作成するのは非常に遅くなります。



Peter Zaitsevブログでは、非標準の「ハッカー」ソリューションが提案されました。



1.目的の構造を使用して、主キーがなくてもインデックスがない新しいテーブル(たとえば、test_new)を作成します。 自動インクリメントフィールドがある場合は、定義からauto_incrementを削除します。

2. INSERT INTO test_new ... SELECTを使用して、このテーブルにデータを入力します

3. test_newと同じ構造で、必要なすべてのキーを持つ別のテーブルを作成します 。 test_structと呼びましょう。

4.テーブルが保存されているディスク上のディレクトリに移動し、test_struct.frmをtest_new.frmに、test_struct.MYIをtest_new.MYIにコピーします。

5. mysqlクライアントを開き、FLUSH TABLESおよびREPAIR TABLE test_newクエリを実行します。



私の場合、REPAIR TABLEは20分かかりました。



考えられる問題。 また、MySQL一時ディレクトリのスペースが不足しました。 私の場合、容量は5 GBの/ tmpでした。 実際、REPAIR TABLEは新しいインデックス用の一時ファイルを作成しますが、最終的には7 GBの重量になりましたが、5 GBには収まりませんでした。 十分なディスクスペースがない場合、MySQLは1分間待機してから、再び何度もそれを見つけようとします。 もちろん、彼はビジネスで忙しいと思って無知のままです:)

MySQLは、 tmpdirパラメータを使用して一時ディレクトリに設定できます。



このハックはどこで使用できますか? 一意のインデックスが存在する非常に大きなテーブルのフィールドを追加、削除、または変更する場合、そのフィールドも非常に大きくなります(ほとんどの場合、文字列フィールド)。 同様のテーブルに一意のインデックスを作成する場合。 そのようなテーブルをダンプから再作成するとき。



追加。 その秘密は何ですか? 一意のインデックスの通常の作成は、行ごと、レコードごとです。 REPAIR TABLEは、ソートを使用してインデックスを一度に作成します。これは非常に高速です。



頑張って



All Articles