MySQL 8.0 新特性:Instant Add Column
一、前言
MySQL 8.0 支持 “快速加列” 功能,既添加字段时可以支持 “INSTANT” 快速完成。通过只修改数据字典的方法来实现大表快速加列,避免之前加列操作必须做的数据拷贝,从而大幅缩小大表加列所需的时间,减少对系统的影响。
支持版本:
MySQL 版本 8.0.12 及以上
腾讯云内核版本 MySQL 5.7 20190830 及以上
腾讯云内核版本 MySQL 8.0 20200630 及以上
二、测试
1. 准备数据
root@mysql 14:12: [sbtest]>select count(*) from sbtest2; +----------+ | count(*) | +----------+ | 200000 | +----------+ 1 row in set (0.04 sec)
2. 添加字段
使用 INSTANT 算法给 20 万行数据表添加字段:
root@mysql 14:17: [sbtest]>ALTER TABLE sbtest2 ADD COLUMN d varchar(10) DEFAULT 'abc',ALGORITHM=INSTANT; Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0
使用 INPLACE 算法给 20 万行数据表添加字段:
root@mysql 14:19: [sbtest]>ALTER TABLE sbtest2 ADD COLUMN e varchar(10) DEFAULT 'abc',ALGORITHM=INPLACE; Query OK, 0 rows affected (6.04 sec) Records: 0 Duplicates: 0 Warnings: 0
对比看 快速加列 的优化效果很明显,几乎是毫秒级就可以完成。
2. 验证
root@mysql 14:18: [sbtest]>select id,d from sbtest2 limit 10; +----+------+ | id | d | +----+------+ | 1 | abc | | 2 | abc | | 3 | abc | | 4 | abc | | 5 | abc | | 6 | abc | | 7 | abc | | 8 | abc | | 9 | abc | | 10 | abc | +----+------+ 10 rows in set (0.00 sec)
三、工作原理
1. 快速加列
在没有 快速加列
的功能时,每次添加字段都需要重建表空间,就需要大量的 IO 及时间。
当使用 快速加列
时,只会修改数据字典,增加 新列的定义
和 新列的默认值
。需要读取数据时 MySQL 会将 新增列的默认值,追加到读取的数据后。
需要写入数据时,使用了新的数据格式 (增加了 instant 标志位 和 "列数" 字段)。
相当于是 伪造列
,那么是否可以一直伪造下去呢?
2. 限制
添加列的操作不能与其它 ALTER TABLE 操作放在同一条语句组合中。
在 MySQL 8.0.29 之前,一列只能作为表的最后一列添加,不支持将列添加到其他列中的任何其他位置。从 MySQL 8.0.29 开始,可以将即时添加的列添加到表中的任何位置。
ROW_FORMAT=COMPRESSED、具有 FULLTEXT 的表、临时表不支持 Instant Add Column。
添加列会评估行的大小,如果超出限制会抛出异常:
ERROR 4092 (HY000): Column can't be added with ALGORITHM=INSTANT as after this max possible row size crosses max permissible row size. Try ALGORITHM=INPLACE/COPY.
3. 表维护
现在回答刚才的问题,是否可以一直伪造下去?
当使用 Instant 添加一个列或多个列时,都会创建一个新的行版本,当超出限制时会抛出异常。
可以通过查询 INFORMATION_SCHEMA.INNODB_TABLES
来查询行版本:
-- Version: 8.0.29 SELECT NAME, TOTAL_ROW_VERSIONS FROM INFORMATION_SCHEMA.INNODB_TABLES;
当 TOTAL_ROW_VERSIONS 大于 64 会报错:ERROR 4080 (HY000): Maximum row versions reached for table test/t1. No more columns can be added or dropped instantly. Please use COPY/INPLACE.
使用 ALTER TABLE 重建表空间时 TOTAL_ROW_VERSIONS 会归 0。