修改MySQL字符集与排序规则是否影响现有索引?需重建varchar索引吗?
我们的数据库原本表和列的默认字符集是utf8,但无法存储表情符号,于是完成了以下修改:
- 将表和列的字符集修改为
utf8mb4 - 将表和列的排序规则修改为
utf8mb4_unicode_ci - 更新JDBC驱动以支持Unicode编码
现在已经能正常存储表情符号了,但有两个技术疑问:
- 修改MySQL数据库的字符集和排序规则时,现有索引会受到影响吗?
- 由于原utf8编码每个字符占用3字节,现utf8mb4编码每个字符占用4字节,是否需要删除现有varchar列的索引并重新创建?
问题1:修改字符集和排序规则对现有索引的影响
肯定会有影响,但不用太慌——MySQL的索引是跟字符集、排序规则绑定的,当你通过ALTER TABLE修改列的字符集和排序规则时,MySQL会自动重建该列关联的所有索引。比如你执行:
ALTER TABLE your_table MODIFY COLUMN your_column VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这时候MySQL会帮你处理索引的重建工作,不用手动删除再创建。
不过要提醒一句:如果表的数据量很大,这个操作会占用一定时间,InnoDB在5.6及以上版本支持在线DDL,但还是会有短暂的锁表窗口,最好挑业务低峰期来做。另外,如果是联合索引,只要其中一列的字符集或排序规则变了,整个联合索引都会被重新构建。
问题2:utf8到utf8mb4的字节变化是否需要手动重建varchar索引?
完全不需要手动操作——原因和上面一样,当你修改列的字符集时,MySQL已经自动帮你把相关索引重建好了。
不过这里有个小坑要注意:MySQL里VARCHAR(N)的N指的是字符数,不是字节数。原来utf8最多3字节/字符,切换到utf8mb4后是4字节/字符,所以列的最大字节占用会从N*3变成N*4。如果原来的列长度设置得刚好卡着InnoDB的行大小上限(65535字节),比如VARCHAR(21844)(218443=65532,接近上限),切换后21844*4=87376就超过了限制,这时候修改会报错,得先把列的字符长度调小一点,比如改成VARCHAR(16383)(163834=65532)。
如果实在不放心索引是否正常,可以用SHOW INDEX FROM your_table;查看索引的细节,或者跑一遍ANALYZE TABLE your_table;更新一下表的统计信息,确保查询优化器能正确使用索引。
内容的提问来源于stack exchange,提问作者Akshay Mehta

