MariaDB10.3、MySQL8から、ALTER構文にinstantの機能が導入されました。
利用できる範囲は限られていますが、その中であれば超高速でALTERが完了します。
たぶん、メタデータだけ書き換えて、実際のデータは初回アクセス時に補完する形をとっているような感じです。
詳細は、公式マニュアルを参考指定だければと思います。
https://mariadb.com/kb/en/library/instant-add-column-for-innodb/
https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
実際にデータを突っ込んでみて、どのくらいALTERが高速になるか試してみました。
以下のようなテーブルを用意して、100万件のデータを入れておきます。
> desc users; +--------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+---------------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | email | varchar(128) | NO | | NULL | | +--------+---------------------+------+-----+---------+-------+
(MySQL5.7)
mysql> alter table users add column money1 bigint unsigned not null; Query OK, 0 rows affected (2.35 sec) Records: 0 Duplicates: 0 Warnings: 0
(MySQL8)
mysql> alter table users add column money1 bigint unsigned not null; Query OK, 0 rows affected (0.16 sec) Records: 0 Duplicates: 0 Warnings: 0
一旦drop。
mysql> alter table users add column money1 bigint unsigned not null, ALGORITHM=INSTANT; Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0
(MariaDB10.3)
MariaDB [test]> alter table users add column money1 bigint unsigned not null; Query OK, 0 rows affected (0.006 sec) Records: 0 Duplicates: 0 Warnings: 0
一旦drop。
MariaDB [test]> alter table users add column money1 bigint unsigned not null, ALGORITHM=INSTANT; Query OK, 0 rows affected (0.007 sec) Records: 0 Duplicates: 0 Warnings: 0
MySQL5.7と比較して、超高速ですね。。
なお、MariaDB10.3もMySQL8も、デフォルトで最後尾へのadd columnはINSTANTとして扱われるようです。
ちなみに、MySQL8のほうが、INSTANTが扱える範囲が広いようです。
以下のような条件でINSTANTが使えるようです。(※公式より引用)
- Adding a column. This feature is referred to as “Instant ADD COLUMN”. Limitations apply. See Section 15.12.1, “Online DDL Operations”.
- Adding or dropping a virtual column.
- Adding or dropping a column default value.
- Modifying the definition of an ENUM or SET column. The same restrictions apply as described above for ALGORITHM=INSTANT.
- Changing the index type.
- Renaming a table. The same restrictions apply as described above for ALGORITHM=INSTANT.
instantが発動したかどうかは、
MariaDB10.3の場合は以下のクエリーによって確認できます。
SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column';
MySQL8の場合は以下。
SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE name LIKE '%{table_name}%';
条件はあるものの、MySQL8は仮想列に対するinstantにも対応しているので、結構使い勝手も広がる予感です。
とはいえ、これまでalterに非常に大きな時間・処理コストがかかっていたのが、一気に超高速になり、非常に素晴らしいと思います。
パッチを提供したTencentに感謝ですね。
あとは、instantで変更をかけて、その後のアクセスでどのくらいIO負荷を持っていかれるか、試してみたいな。。
以上
コメントがあればどうぞ