一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • InfluxDB

  • MongoDB

  • MySql

    • mysql之索引的工作机制
    • mysql基本语法学习小结
    • mysql之锁与事务详解
    • MySql性能监控工具MyTop
    • mysql之数据库导入导出
    • MySql插入唯一键冲突的三种可选方式
    • mysql表锁死解决办法
    • mysql之给现有表新增自增字段
    • mysql 新增多列写法
    • Mysql DDL出现长时间等待MDL问题分析
    • MySql查询时间戳日期互转
    • mysql索引过长Specialed key was too long问题记录
      • II. 其他
        • 1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
        • 2. 声明
        • 3. 扫描关注
    • MySql Timestamp默认值限制问题
    • MySql最大连接数查看与修改
    • Mysql 字符集不一致问题
    • MySql并发插入死锁引来的锁分析
    • MySql表字段修改记录
  • 数据库
  • MySql
一灰灰
2019-07-04

mysql索引过长Specialed key was too long问题记录

在创建要给表的时候遇到一个有意思的问题,提示Specified key was too long; max key length is 767 bytes,从描述上来看,是Key太长,超过了指定的 767字节限制

下面是产生问题的表结构

CREATE TABLE `test_table` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(1000) NOT NULL DEFAULT '',
  `link` varchar(1000) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
1
2
3
4
5
6
7

我们可以看到,对于name,我们设置长度为1000可变字符,因为采用utf8mb4编码, 所以它的大小就变成了 1000 * 4 > 767

所以再不修改其他配置的前提下,varchar的长度大小应该是 767 / 4 = 191

有兴趣的同学可以测试下,分别指定name大小为191, 192时,是不是前面的可以创建表成功,后面的创建表失败,并提示错误Specified key was too long; max key length is 767 bytes

解决办法一

  • 使用innodb引擎
  • 启用innodb_large_prefix选项,修改约束扩展至3072字节
  • 重新创建数据库

my.cnf配置

set global innodb_large_prefix=on;
set global innodb_file_per_table=on;
set global innodb_file_format=BARRACUDA;
set global innodb_file_format_max=BARRACUDA;
1
2
3
4

上面这个3072字节的得出原因如下

我们知道InnoDB一个page的默认大小是16k。由于是Btree组织,要求叶子节点上一个page至少要包含两条记录(否则就退化链表了)。

所以一个记录最多不能超过8k。又由于InnoDB的聚簇索引结构,一个二级索引要包含主键索引,因此每个单个索引不能超过4k (极端情况,pk和某个二级索引都达到这个限制)。

由于需要预留和辅助空间,扣掉后不能超过3500,取个“整数”就是(1024*3)。

解决办法二

在创建表的时候,加上 row_format=DYNAMIC

CREATE TABLE `test_table` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  `link` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 row_format=DYNAMIC;
1
2
3
4
5
6
7

这个参数的作用如下

MySQL 索引只支持767个字节,utf8mb4 每个字符占用4个字节,所以索引最大长度只能为191个字符,即varchar(191),若想要使用更大的字段,mysql需要设置成支持数据压缩,并且修改表属性 row_format ={DYNAMIC|COMPRESSED}

# II. 其他

# 1. 一灰灰Blog (opens new window): https://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

# 2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

  • 微博地址: 小灰灰Blog (opens new window)
  • QQ: 一灰灰/3302797840

# 3. 扫描关注

一灰灰blog

QrCode

知识星球

goals

编辑 (opens new window)
#Mysql
上次更新: 2021/10/15, 19:56:22
MySql查询时间戳日期互转
MySql Timestamp默认值限制问题

← MySql查询时间戳日期互转 MySql Timestamp默认值限制问题→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×