web-dev-qa-db-ja.com

大きなMySQL InnoDBテーブルの変更

新しい列を追加したり、新しいインデックスを追加したりすると、1,000万行を超えるMySQLの大きなinnodbテーブルの場合、数時間から数日かかることがあります。これら2つのケースで大きなinnodbテーブルのパフォーマンスを向上させる最良の方法は何ですか?より多くのメモリ、構成の微調整(たとえば、 sort_buffer_size または innodb_buffer_pool_size の増加)、または何らかのトリック?テーブルを直接変更する代わりに、新しいテーブルを作成して変更し、古いデータを新しいものにコピーすることができます。これは ISAMテーブル および 複数の変更 に便利です。 :

CREATE TABLE tablename_tmp LIKE tablename;
ALTER TABLE tablename_tmp ADD fieldname fieldtype;
INSERT INTO tablename_tmp SELECT * FROM tablename;
ALTER TABLE tablename RENAME tablename_old;
ALTER TABLE tablename_tmp RENAME tablename;

Innodbテーブルにもお勧めですか、それとも、ALTER TABLEコマンドが機能しないことですか?

37
0x4a6f4672

Edit 2016:私たちは最近(2016年8月)にgh-ostをリリースしました。

今日、MySQLのオンライン変更テーブルを実行できるいくつかのツールがあります。これらは:

「通常の」「ALTER TABLE」を考えてみましょう:

大きなテーブルはALTERに時間がかかります。 innodb_buffer_pool_sizeは重要であり、他の変数も同様ですが、非常に大きなテーブルでは無視できます。時間がかかるだけです。

MySQLがテーブルに対してALTERを行うのは、新しいフォーマットで新しいテーブルを作成し、すべての行をコピーしてから切り替えることです。この間、テーブルは完全にロックされています。

あなた自身の提案を検討してください:

おそらく、すべてのオプションの中で最悪のパフォーマンスを発揮します。何故ですか? InnoDBテーブルを使用しているため、INSERT INTO tablename_tmp SELECT * FROM tablenameはトランザクションになります。 hugeトランザクション。通常のALTER TABLEよりもさらに負荷がかかります。

さらに、テーブルに(INSERTDELETEUPDATE)を書き込まないように、その時点でアプリケーションをシャットダウンする必要があります。もしそうなら-あなたのトランザクション全体は無意味です。

オンラインツールが提供するもの

ツールはすべて同じように機能するわけではありません。ただし、基本は共有されています。

  • スキーマが変更された「シャドウ」テーブルを作成する
  • トリガーを作成して使用し、元のテーブルからゴーストテーブルに変更を伝播します。
  • それらはゆっくりとテーブルからシャドウテーブルにすべての行をコピーします。それらはチャンクで行います。たとえば、一度に1,000行です。
  • 元のテーブルにアクセスして操作することができる間、上記のすべてを行います。
  • 満足したら、RENAMEを使用して2つを入れ替えます。

openark-kitツールは、3.5年前から使用されています。 Perconaツールは数か月前のものですが、おそらく前者よりもさらにテストされています。 FacebookのツールはFacebookでうまく機能すると言われていますが、平均的なユーザーに対する一般的なソリューションは提供していません。自分では使っていません。

Edit 2016:gh-ostはトリガーなしのソリューションであり、マスターへのマスター書き込み負荷を大幅に削減し、移行書き込み負荷を通常から切り離します負荷。監査可能、制御可能、テスト可能です。私たちはそれをGitHubの内部で開発し、オープンソースとしてリリースしました。今日は、gh-ostを介してすべての製品の移行を行っています。詳細はこちら こちら

各ツールには独自の制限があります。ドキュメントをよく確認してください。

保守的な方法

保守的な方法は、アクティブ-パッシブマスター-マスターレプリケーションを使用し、スタンバイ(パッシブ)サーバーでALTERを実行してから、役割を切り替えて、以前の方法でALTERを再度実行することですアクティブサーバー、パッシブになりました。これも適切なオプションですが、追加のサーバーが必要で、レプリケーションについての深い知識が必要です。

67
Shlomi Noach

参照されているテーブルのねじの名前を変更します。

tablenameの子であるtable_2と言うと、ALTER TABLE tablename RENAME tablename_old;table_2tablename_oldを指すようになります。

これで、table_2を変更せずにtablenameを指すようにすることはできません。すべての子と参照されるテーブルで変更を加え続ける必要があります。

0
Lokesh