web-dev-qa-db-ja.com

大きなテーブルに列を追加するMySQLのパフォーマンス

Ubuntu 13.10でapt-getを使用してInnoDBをローカルにインストールしたMySQL 5.5.37を持っています。私のマシンは、デスクトップ上のi7-3770 + 32Gbメモリ+ SSDハードドライブです。 150万件のレコードのみを含むテーブル「mytable」の場合、次のDDLクエリは20分以上かかります(!):

ALTER TABLE mytable ADD some_column CHAR(1) NOT NULL DEFAULT 'N';

それを改善する方法はありますか?私はチェックした

show processlist;

そしてそれはそれが何らかの理由で私のテーブルをコピーしていることを示していました。それは邪魔なほど不便です。このコピーをオフにする方法はありますか?大きなテーブルに列を追加するパフォーマンスを向上させる他の方法はありますか?

それ以外は、私のDBは比較的小さく、ダンプサイズは1.3Gbしかありません。したがって、(理論的には)メモリに100%収まるはずです。

役立つ設定はありますか? Preconaへの移行により、何か変化はありますか?

追加:私は持っています

innodb_buffer_pool_size = 134217728
13
Artem

大きなテーブルに列を追加するパフォーマンスを向上させる他の方法はありますか?

短い答え:いいえ。 ENUM値とSET値を即座に追加でき、書き込みのみをロックしながらセカンダリインデックスを追加できますが、テーブル構造を変更するには常にテーブルコピーが必要です。

長い答え:あなたの本当の問題は実際のパフォーマンスではなく、ロック時間です。遅いかどうかは問題ではなく、ALTER TABLEが完了するまで他のクライアントがクエリを実行できないことだけが問題です。その場合、いくつかのオプションがあります。

  1. Perconaツールキットの pt-online-schema-change を使用できます。最初にデータをバックアップしてください!これが最も簡単な解決策ですが、すべてのケースで機能するわけではありません。

  2. 外部キーを使用せず、インデックスが多数あるために処理が遅い場合は、必要な変更を加えたテーブルのコピーを作成し、セカンダリインデックスを作成せず、データを入力して作成する方が速い場合があります。最後に単一の変更テーブルを持つすべてのインデックス。

  3. Amazon RDSでホストされている場合のように、レプリカを作成するのが簡単な場合は、マスター/マスターレプリカを作成し、そこで変更テーブルを実行して、同期を取り戻し、完了後にインスタンスを切り替えることができます。

[〜#〜]更新[〜#〜]

他の人が述べたように、MySQL 8.0 INNODBはインスタント列の追加のサポートを追加しました。それは魔法の解決策ではありません、それは制限と副作用があります-それは最後の列だけであることができます、テーブルは全文索引を持っていてはなりません-など-しかし多くの場合に役立つはずです。

明示的なALGORITHM=INSTANT LOCK=NONEパラメータを指定でき、インスタントスキーマの変更が不可能な場合、MySQLはINPLACEまたはCOPYにフォールバックする代わりにエラーで失敗します。例:

ALTER TABLE mytable
ADD COLUMN mycolumn varchar(36) DEFAULT NULL,
ALGORITHM=INPLACE, LOCK=NONE;

https://mysqlserverteam.com/mysql-8-0-innodb-now-supports-instant-add-column/

17
Pedro Werneck

MariaDb 10.3、MySQL 8.0、およびおそらく他のMySQLバリアントには、「インスタントADD COLUMN」機能があり、ほとんどの列(いくつかの制約があります。ドキュメントを参照)は、テーブルを再構築せずに即座に追加できます。

4
ColinM

オンラインDDLはどうですか?

http://www.tocker.ca/2013/11/05/a-closer-look-at-online-ddl-in-mysql-5-6.html

多分あなたは代わりにTokuDBを使うでしょう:

http://www.tokutek.com/products/tokudb-for-mysql/

構造が変更されるため、列を追加または削除するときにテーブルのコピーを回避する方法はありません。テーブルのコピーなしでセカンダリインデックスを追加または削除できます。

テーブルデータがメモリにありません。インデックスはメモリに常駐できます。

150万レコードは多くの行ではなく、20分はかなり長いようですが、おそらく行が大きく、インデックスが多数あります。

テーブルのコピー中も、テーブルから行を選択できます。ただし、更新を行おうとすると、ALTERが完了するまで更新はブロックされます。

1
Marcus Adams

私はこれがかなり古い質問であることを知っていますが、今日私は同様の問題に遭遇しました。新しいテーブルを作成し、古いテーブルを新しいテーブルにインポートすることにしました。何かのようなもの:

CREATE TABLE New_mytable  LIKE mytable ;

ALTER TABLE New_mytable  ADD some_column CHAR(1) NOT NULL DEFAULT 'N';

insert into New_mytable  select * from mytable ;

その後

START TRANSACTION;
insert into New_mytable  select * from mytable where id > (Select max(id) from New_mytable) ;

RENAME TABLE mytable TO Old_mytable;

RENAME TABLE New_mytable TO mytable;
COMMIT;

これによって更新プロセスが速くなることはありませんが、ダウンタイムは最小限に抑えられます。

お役に立てれば。

0
Nebu