8

最大約17GBのサイズで3800万のエントリを持つMySQLデータベースがあります。現時点では、1つの列のサイズを大きくする(varchar40からvarchar80)と、さらに列を追加する必要があります。

変更する必要のあるフィールドを含め、多くのフィールドにインデックスが付けられています。これは、アプリケーションが機能するために必要な固有のペアの一部です。昨日変更を加えようとしたところ、停止を切り取ってサービスを再開することにしたときに、クエリは終了せずにほぼ4時間実行されました。

このサイズのものに変更を加える最も効率的な方法は何ですか?

これらのエントリの多くも古いものであり、エントリをシャードオフする良い方法があるが、テーブルをはるかに管理しやすいサイズにすることでこの問題に役立つ可能性のあるエントリをまだ利用できる場合。

4

3 に答える 3

8

いくつかの選択肢があります。

いずれにせよ、このようなことをする前にバックアップを取る必要があります。

1つの可能性は、サービスをオフラインにして、試したとおりに適切な場所で実行することです。その場合は、キーチェックと制約を無効にする必要があります。

ALTER TABLE bigtable DISABLE KEYS;
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE (whatever);
ALTER TABLE (whatever else);
...
SET FOREIGN_KEY_CHECKS=1;
ALTER TABLE bigtable ENABLE KEYS;

これにより、ALTERTABLE操作を高速化できます。ENABLE KEYSを実行すると、インデックスが一度に再生成されます。

もう1つの可能性は、必要な新しいスキーマを使用して新しいテーブルを作成し、新しいテーブルのキーを無効にしてから、@ Baderが提案したように実行し、古いテーブルの内容を挿入することです。

新しいテーブルが作成されたら、そのキーを再度有効にし、古いテーブルの名前を「old_bigtable」などの名前に変更してから、新しいテーブルの名前を「bigtable」に変更します。

新しいテーブルにデータを入力している間、サービスをオンラインに保つことができる可能性があります。しかし、それはうまくいかないかもしれません。

3番目の可能性は、巨大なテーブルを(フラットファイルに)ダンプしてから、新しいレイアウトで新しいテーブルにロードすることです。これは、テーブルのバックアップを無料で取得できることを除けば、2番目の可能性とほとんど同じです。SELECT DATA INTO OUTFILEとを使用すると、これをかなり高速に実行できますLOAD DATA INFILE。これを行うには、サーバーマシンのファイルシステムにアクセスできる必要があります。

いずれの場合も、制約とキーを無効にしてから再度有効にして、処理を高速化します。

于 2012-10-19T16:46:53.247 に答える
5

NewTableなど、別の名前で必要な新しい構造を使用して新しいテーブルを作成します。

次に、次のクエリを使用して、古いテーブルからこの新しいテーブルにデータを挿入します。

INSERT INTO NewTable (field1, field2, etc...) SELECT field1, field2, ... FROM OldTable

これが完了したら、古いテーブルを削除して、新しいテーブルの名前を元の名前に変更できます。

DROP TABLE `OldTable`;
RENAME TABLE `NewTable` TO `OldTable` ;

私は非常に大きなテーブルでこのアプローチを試しましたが、テーブルを変更するよりもはるかに高速です。

于 2012-10-19T16:34:33.810 に答える
2

MySQL 5.1および5.5では、特定の変更ステートメントが拡張され、テーブル全体を書き直さずに構造を変更するだけになりました(http://dev.mysql.com/doc/refman/5.5/en/alter-table.html-で検索-場所)。これを利用できるかどうかは、行っている変更の種類と使用しているエンジンによって異なりますが、最も価値のあるものはInnoDBプラグインです。特定の変更の場合、テーブル全体が書き換えられますが。

これらの問題が発生した場合、通常、レプリカデータベースを活用しようとします。追加し、削除しない限り、最初にレプリカに対してDDLを実行してから、レプリカをマスターロールに昇格させるための短時間の停止をスケジュールできます。RDSを使用している場合、これはレプリカインスタンスの推奨される使用法の1つですhttp://aws.amazon.com/about-aws/whats-new/2012/10/11/amazon-rds-mysql-rr -プロモーション/

他のいくつかの選択肢は次のとおりです。

  • レコードのサブセットを選択して、目的の構造を持つ新しいテーブルにします(INTO OUTFILEテーブルのロックを回避するために使用します)。完了したら、メンテナンスウィンドウや、最初のデータコピー以降に元のテーブルで変更されたレコードをスケジュールできREPLACE INTOますUPDATE。更新が完了するRENAME TABLE...と、両方のテーブルのいずれかが変更をラップします。
  • Perconaのpt-online-schema-changeのようなツールを使用する:http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html。このツールはトリガーで機能するため、変更するテーブルに既にトリガーがある場合、これはニーズに合わない可能性があります。
于 2012-10-19T18:16:05.360 に答える