MySQL导入报错“Index column size too large. The maximum column size is 767 bytes.”

0    289    3

Tags:

👉 本文共约2597个字,系统预计阅读时间或需10分钟。

现象

MySQL在大字段上创建索引,或者字段的长度时,可能会遇到如下错误:

ERROR 1709 (HY000) at line 33: Index column size too large. The maximum column size is 767 bytes.

原因

原因是Mysql的innodb引擎表,在缺省状态下,缺省情况下,索引键前缀长度限制最长为767字节。

产生此问题的原因是因为MySQL Innodb索引字段长度最大为767字节,如果索引大小超过767字节则会引发该错误。

对于多字节字符集的大字段或者多字段组合,创建索引时会出现该问题。

详情见官方文档:https://dev.mysql.com/doc/refman/5.6/en/innodb-limits.html

By default, the index key prefix length limit is 767 bytes. See Section 13.1.13, “CREATE INDEX Statement”. For example, you might hit this limit with a column prefix index of more than 255 characters on a TEXT or VARCHAR column, assuming a utf8mb3 character set and the maximum of 3 bytes for each character. When the innodb_large_prefix configuration option is enabled, the index key prefix length limit is raised to 3072 bytes for InnoDB tables that use the DYNAMIC or COMPRESSED row format.

如官方文档上所写,如果要在text或varchar类型字段上创建索引,假设字符集为utfmb3,那么每个字符占3个字节,那么这类字段的字符长度最长则是767/3 ≈ 255个字符;假设字符集为utf8mb4,那么每个字符占4个字节,那么这类字段的字符长度最长则是767/4 ≈ 191个字符。

以utf8mb4字符集字符串类型字段为例。utf8mb4是4字节字符集,默认支持的索引字段最大长度是191字符(767字节/4字节每字符≈191字符),因此在varchar(255)或char(255)类型字段上创建索引会失败。

只有当innodb_large_prefix配置选项被启用时,对于使用DYNAMICCOMPRESSED行格式的InnoDB表,索引键前缀长度限制将提高到3072字节。

看个例子,我有一张表a_test,表结构如下所示。

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

可以看到表的Row_Format为compact,那么在字段biz_id(varchar(191))上建立索引idx_biz_id(biz_id)时,索引键前缀长度有最长为767字节的限制。

可以看到此时可以成功创建索引idx_biz_id(biz_id),接下来,我们将biz_id字段的修改为192,看看会发生什么。

此时如果想成功修改字段长度,需要开启innodb_large_prefix,并且设置表a_test的row_format为DYNAMICCOMPRESSED

查看需要开启innodb_large_prefix是否开启:

备注:8.0之后,该参数被移除,默认开启。innodb_large_prefix: Enables longer keys for column prefix indexes. Removed in MySQL 8.0.0.

查看表的row_format。

修改表的row_format为Dynamic。

验证一下:

可见,当修改表的row_format为dynamic后,可以biz_id字段的字符长度可以超过191了。

如果报错,可以根据报错的行数打开sql文件,查看第33行代码,发现建表语句如下:

解决

查看:

修改:

如果是MySQL rds,那么可以在界面修改参数 innodb_large_prefix 参数值为 ON,然后单击 提交。该参数在5.6中默认为 off,可以修改为 on;在5.7中默认为 on,不用修改。

也可以通过命令修改:

所以,建表语句可以修改为:

mysql中表的row_format

在早期的InnoDB版本中,由于文件格式只有一种,因此不需要为此文件格式命名。随着InnoDB引擎的发展,开发出了不兼容早期版本的新文件格式,用于支持新的功能。为了在升级和降级情况下帮助管理系统的兼容性,以及运行不同的MySQL版本,InnoDB开始使用命名的文件格式。

  1. Antelope: 先前未命名的,原始的InnoDB文件格式。它支持两种行格式:COMPACT 和 REDUNDANT。MySQL5.6的默认文件格式。可以与早期的版本保持最大的兼容性。不支持 Barracuda 文件格式。

  2. Barracuda: 新的文件格式。它支持InnoDB的所有行格式,包括新的行格式:COMPRESSED 和 DYNAMIC。与这两个新的行格式相关的功能包括:InnoDB表的压缩,长列数据的页外存储和索引建前缀最大长度为3072字节。

在 mysql 5.7.9及以后版本,默认行格式由innodb_default_row_format变量决定,它的默认值是DYNAMIC。

在早期的InnoDB版本中,由于文件格式只有一种,因此不需要为此文件格式命名。随着InnoDB引擎的发展,开发出了不兼容早期版本的新文件格式,用于支持新的功能。为了在升级和降级情况下帮助管理系统的兼容性,以及运行不同的MySQL版本,InnoDB开始使用命名的文件格式。

  1. Antelope: 先前未命名的,原始的InnoDB文件格式。它支持两种行格式:COMPACT 和 REDUNDANT。MySQL5.6的默认文件格式。可以与早期的版本保持最大的兼容性。不支持 Barracuda 文件格式。

  2. Barracuda: 新的文件格式。它支持InnoDB的所有行格式,包括新的行格式:COMPRESSED 和 DYNAMIC。与这两个新的行格式相关的功能包括:InnoDB表的压缩,长列数据的页外存储和索引建前缀最大长度为3072字节。

在 msyql 5.7.9 及以后版本,默认行格式由innodb_default_row_format变量决定,它的默认值是DYNAMIC,也可以在 create table 的时候指定ROW_FORMAT=DYNAMIC。用户可以通过命令 SHOW TABLE STATUS LIKE'table_name' 来查看当前表使用的行格式,其中 row_format 列表示当前所使用的行记录结构类型。

一行记录可以以不同的格式存在InnoDB中,行格式分别是Compact、Redundant、Dynamic和Compressed行格式。

总结

Mysql的innodb引擎表,在缺省状态下,索引键前缀长度限制最长为767字节(假设字符集为utf8mb4,那么每个字符占4个字节,那么这类字段的字符长度最长则是767/4 ≈ 191个字符)。只有当innodb_large_prefix配置选项被启用时,对于使用DYNAMICCOMPRESSED行格式的InnoDB表,索引键前缀长度限制将提高到3072字节(对于utf8mb4来说就是768个字符)。

在myql 5.7.9及以后版本,默认行格式由innodb_default_row_format变量决定,它的默认值是DYNAMIC。8.0之后,innodb_large_prefix参数被移除,默认开启。

参考

https://mp.weixin.qq.com/s/VOWjt-1-fALz4WsR_iBOMg

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部