web-dev-qa-db-ja.com

ALTER TABLE ADD COLUMNに時間がかかります

データベースのテーブル(main_table)に「location」という列を追加しようとしていました。私が実行したコマンドは

ALTER TABLE main_table ADD COLUMN location varchar (256);

Main_tableには2,000,000を超える行が含まれます。 2時間以上実行し続けても、まだ完了していません。

mytopを使用してこのデータベースのアクティビティを監視し、クエリが他のクエリプロセスによってロックされていないことを確認しようとしましたが、そうではないようです。長い時間がかかるはずですか?実際、このコマンドを実行する前にマシンをリブートしました。現在、このコマンドはまだ実行中です。私は何をすべきかわかりません。

61
fanchyna

きみの ALTER TABLEステートメントは、mysqlが新しい列を含むテーブルのすべての行を書き直す必要があることを意味します。 200万を超える行があるので、かなりの時間がかかることは間違いありません。その間、サーバーはほとんどの場合IOにバインドされるでしょう。通常、次の操作を実行するとパフォーマンスが向上します。

CREATE TABLE main_table_new LIKE main_table;
ALTER TABLE main_table_new ADD COLUMN location varchar(256);
INSERT INTO main_table_new (fields_in_main_table) SELECT * FROM main_table;
RENAME TABLE main_table TO main_table_old, main_table_new TO main_table;
DROP TABLE main_table_old;

この方法では、空のテーブルに列を追加し、基本的に、新しいテーブルにデータを書き込みます。このテーブルには、他の誰も見ていないリソースがロックされていないと確信できます。

171
Romain

これに対する適切な答えは、 pt-online-schema-change または gh-ost のような機能を使用することだと思います。

これで40億行以上の移行を行いましたが、ダウンタイムは1分未満で最大10日かかります。

Perconaは上記と非常によく似た方法で動作します

  • 一時テーブルを作成する
  • 一時テーブルにレプリケートされるように、最初のテーブルにトリガーを作成(挿入、更新、削除用)
  • 小さなバッチで、データを移行する
  • 完了したら、テーブルの名前を新しいテーブルに変更し、他のテーブルを削除します
24
Pratik Bothra

テーブルの変更は、あなたの場合のようにビッグデータでは長い時間がかかるため、このような状況では使用しないでください。また、次のようなコードを使用してください。

select main_table.*, 
  cast(null as varchar(256)) as null_location, -- any column you want accepts null
  cast('' as varchar(256)) as not_null_location, --any column doesn't accept null
  cast(0 as int) as not_null_int, -- int column doesn't accept null
into new_table 
from main_table;

drop table main_table;
rename table new_table TO main_table;
1
ZORRO_BLANCO