我使用的是 MySQL 5.7.17
当我将一个大型测试表的数据类型从 varchar(45) 更改为 varchar(50) 时,只用了不到一秒钟就完成了。
我找不到一个很好的文档来解释为什么这会发生得如此之快。请帮忙。
(我们将在我们庞大的生产表上将数据类型从 varchar(45) 更改为 varchar(50),这将有助于我们计算所需的停机时间。)
我使用的是 MySQL 5.7.17
当我将一个大型测试表的数据类型从 varchar(45) 更改为 varchar(50) 时,只用了不到一秒钟就完成了。
我找不到一个很好的文档来解释为什么这会发生得如此之快。请帮忙。
(我们将在我们庞大的生产表上将数据类型从 varchar(45) 更改为 varchar(50),这将有助于我们计算所需的停机时间。)
一个表有一个“定义”(CREATE TABLE...
),它有数据和索引。
如果可以在不更改数据存储方式的情况下执行 ALTER
,那么它可以(在大多数情况下,以及在最近的版本中)通过更改定义而不触及实际数据来实现。
那么,让我们看看如何存储 VARCHAR(N)
列:
对于简短的定义(即小N):
* 1-byte length field
* a variable number of bytes to hold the actual _characters_
对于更大的列(N=256 肯定符合条件):
* 2-byte length field
* a variable number of bytes to hold the actual characters
因此,从 N=40 切换到 N=50 不需要触及数据,但我认为从 N=45 切换到 N=266 需要重写所有数据。
(我对 N 有点含糊,因为一个“字符”可以占用多个“字节”,具体取决于 COLLATION
。)
也许最慢的 ALTER
是更改 PRIMARY KEY
。这需要重新排列数据,因为它是由 PK 排序的,并且需要重建所有二级索引,因为它们包含 PK 的副本。
在频谱的中间是一些 INDEX
操作。 DROP INDEX
非常便宜——从定义中删除,然后清理它消耗的空间。 ADD INDEX
成本更高,因为它需要填充一个新的 BTree 来保存索引。同时,数据和任何其他二级索引可以保持不变。然而,代码必然很棘手——如果在构建索引时修改了行会怎样。
这个应该更快,没有截断值,因为你 正在增加长度。
但我建议在更改现有表后复制一份 长度,您可以重命名表。表的重命名应该是 更快。