InnoDB 5.6联合索引键长计算疑问:VARCHAR(256)报错255为何正常?
InnoDB 5.6索引键长计算规则与你的问题解析
核心限制背景
InnoDB 5.6默认开启innodb_large_prefix=OFF,此时有两个关键索引长度限制:
- 单个索引条目(联合索引所有列的索引部分总和)最大长度为767字节
- 单个列的索引部分(即使是前缀)最大长度也不能超过767字节
键长计算的具体规则
- 固定长度列:如
bigint(20)直接按实际字节数计算(8字节),必须完整加入索引,无法截断。 - 变长字符列(varchar):
- 字符集为utf8(即InnoDB的utf8mb3,每个字符最多3字节)时,计算方式为:
字符数 × 3 + 长度标识字节数 - 长度标识规则:列定义字符数≤255时加1字节,>255时加2字节(需要更多空间存储长度值)
- 在联合索引中,仅最后一个变长列会被自动截断前缀,以满足总长度不超过767字节;前面的变长列会完整保留(保证前缀匹配的有效性)
- 字符集为utf8(即InnoDB的utf8mb3,每个字符最多3字节)时,计算方式为:
你的问题具体分析
报错场景(REQ_NAME为varchar(256))
- USER_ID:8字节(固定长度)
- TYPE:
31×3 +1 =94字节(varchar(31)≤255,加1字节长度标识) - REQ_NAME:
256×3 +2=770字节(varchar(256)>255,加2字节长度标识)
此时REQ_NAME的单列最大长度770字节已经超过767字节的限制,即使放在联合索引最后,InnoDB也不允许创建该索引,直接触发max key length is 767 bytes错误。
成功场景(REQ_NAME改为varchar(255))
- 前两列总长度:
8+94=102字节 - 剩余可用索引长度:
767-102=665字节 - REQ_NAME为varchar(255),长度标识1字节,因此可用于存储字符的字节数为
665-1=664字节,对应字符数为664÷3≈221(向下取整) - 最终REQ_NAME在索引中仅保留前221个字符,占用
221×3+1=664字节,总索引长度102+664=766字节,符合767字节限制,因此索引创建成功。
避免类似问题的建议
- 优先选择固定长度类型存储ID类字段(如bigint),减少索引长度开销
- 对于变长字符列,根据实际业务需求合理设置字符数,避免冗余长度
- 若需支持更长的索引,可开启
innodb_large_prefix=ON(需配合innodb_file_format=Barracuda),此时联合索引总长度可扩展至3072字节,但单列索引仍限制为767字节
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

