43

1000万行を超える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コマンドが実行することだけですか?

4

2 に答える 2

72

2016年の編集:最近(2016年8月)リリースgh-ostし、それを反映するように回答を変更しました。

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

「通常の」`ALTERTABLE`について考えてみましょう。

大きなテーブルはに時間がかかりますALTERinnodb_buffer_pool_size重要であり、他の変数も重要ですが、非常に大きなテーブルでは、それらはすべて無視できます。時間がかかるだけです。

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

あなた自身の提案を考えてください:

ほとんどの場合、すべてのオプションの中で最悪のパフォーマンスを示します。何故ですか?InnoDBテーブルを使用しているINSERT INTO tablename_tmp SELECT * FROM tablenameため、トランザクションが発生します。巨大な取引。通常よりもさらに多くの負荷が発生しますALTER TABLE

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

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

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

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

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

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

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

保守的な方法

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

于 2012-07-12T11:03:27.383 に答える
0

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

table_2どちらが子であるかを言うとtablename、onALTER TABLE tablename RENAME tablename_old; table_2はを指し始めtablename_oldます。

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

于 2015-10-08T22:23:10.463 に答える