【MySQL】索引长度的一些限制

有同学问到InnoDB的索引长度问题,简单说几个tips。


MySQL的每个单表中所创建的索引长度是有限制的,且对不同存储引擎下的表有不同的限制。

  • myisam表,单列索引,最大长度不能超过 1000 bytes,否则会报警,但是创建成功,最终创建的是前缀索引(取前333个字符)。
  • myisam表,组合索引,索引长度和不能超过 1000 bytes,否则会报错,创建失败;
  • innodb表,单列索引,超过 767 bytes的,给出warning,最终索引创建成功,取前缀索引(取前 255 字符)。
  • innodb表,组合索引,各列长度不超过 767 bytes ,如果有超过 767 bytes 的,则给出报警,索引最后创建成功,但是对于超过 767 字节的列取前缀索引,与索引列顺序无关,总和不得超过 3072 ,否则失败,无法创建。

测试:

作者只对mysql innodb 引擎,utf8字符集定义的表做了实际的测试,myisam留给读者

版本:

新建测试表:

组合索引中有大于 767 bytes的字段,产生告警

结合上边两个测试结果,可以看到组合索引长度之和大于 767 bytes并无影响,当有某个字段定义长度大于 767 bytes(1000*3)时,仅产生告警,但不影响创建,超长字段会取前 255 字符作为前缀索引,并且结合下图得知,和组合索引中字段出现的顺序并无关系。

可以看到,由于每个字段占用255*3, 因此这个索引的大小是3825>3072,报错。

为什么3072

InnoDB一个page的默认大小是 16 k。由于是Btree组织,要求叶子节点上一个page至少包含两条记录(否则就退化链表了)。所以一个记录最多不能超过 8 k。又由于InnoDB的聚簇索引结构,一个二级索引要包含主键索引,因此每个单个索引不能超过 4 k(极端情况,pk和某个二级索引都达到这个限制)。由于需要预留和辅助空间,扣掉后不能超过 3500 ,取个“整数”就是(1024*3)。

单列索引限制

默认情况下,InnoDB 引擎单一字段索引的长度最大为 767 字节,同样的,前缀索引也有同样的限制。当使用 UTF-8 字符集,每一个字符使用 3 字节来存储,767=256*3-1,在 TEXT 或者 VARCHAR 类型的字段上建立一个超过 255 字符数的前缀索引时就会遇到问题。至于为什么字符长度限制在 256 内,我猜是为提高索引效率,应为varchar类型需要额外的字节保留其长度信息,256 就将其限定在一个字节了。但是在5.5以后,开始支持4个字节的uutf8。255×4>767, 于是增加了一个参数叫做innodblargeprefix。这个参数默认值是OFF,当改为ON时,允许列索引最大达到 3072 字节。要求表的 row_format 需要使用 compressed 或者 dynamic。

主要字符集的计算方式:

  • latin1 = 1 byte = 1 character
  • uft8 = 3 byte = 1 character
  • gbk = 2 byte = 1 character

使用前缀索引带来的风险:

INNODB的索引会限制单独Key的最大长度为 767 字节,超过这个长度必须建立小于等于 767 字节的前缀索引。 此外,BLOB和TEXT类型的列只能创建前缀索引。 前缀索引能提高索引建立速度和检索速度,但是下面情况是无法使用前缀索引的:

  1. 索引覆盖扫描
  2. 通过索引的排序(order by, group by)

还是在上面的测试表上:

author:bill

2015年 12月 08日

参考

  1. mysql索引长度的一些限制
  2. 关于InnoDB索引长度限制的tips
时间: 2024-10-16 05:02:54

【MySQL】索引长度的一些限制的相关文章

MySQL索引长度限制问题

在修改表结构时出现了错误:Specified key was too long;max key length is 1000 bytes. MySQL版本为Server version: 5.1.36, 执行SQL为: alter table pre_common_diy_data modify column targettplname varchar(255); 如果是按一个字符占两个字节计算 2*255=510 并没有超过1000字符,怎么会报错呢? 在查询相关资料后发现,MySQL MyI

mysql索引长度

http://blog.csdn.net/qsc0624/article/details/51335632 大家应该知道InnoDB单列索引长度不能超过767bytes,联合索引还有一个限制是长度不能超过3072. mysql> CREATE TABLE `tb` ( ->   `a` varchar(255) DEFAULT NULL, ->   `b` varchar(255) DEFAULT NULL, ->   `c` varchar(255) DEFAULT NULL,

mysql 索引长度和区分度

首先  索引长度和区分度是相互矛盾的, 索引长度太短,那么区分度就很低,吧索引长度加长,区分度就高,但是索引也是要占内存的,所以我们需要找到一个平衡点: 那么这个平衡点怎么来定? 比如用户表有个字段 username ,要给他加索引,问题是索引长度多少合适? 其实我们知道 百家姓里面有百多个姓 ,但是大多数人的姓 集中在前十多个:如果我设置索引索引长度为1,对染占内存少,但是区分度低, 区分度低索引的效率越低.太长则占内存: 首先你要知道 mysql的索引都是排好序的.如果区分度高排序越快,区分

修改Mysql索引长度限制

mysql 索引过长1071-max key length is 767 byte问题create table: Specified key was too long; max key length is 767 bytes 原因数据库表采用utf8编码,其中varchar(255)的column进行了唯一键索引而mysql默认情况下单个列的索引不能超过767位(不同版本可能存在差异) 于是utf8字符编码下,255*3 byte 超过限制 解决1 使用innodb引擎:2 启用innodb_l

mysql索引长度的一些限制

一.myisam存储引擎 1. 数据库版本:阿里云RDS MySQL5.1 mysql> select @@version;+-------------------------------+| @@version |+-------------------------------+| 5.1.61-Alibaba-rds-201404-log |+-------------------------------+1 row in set (0.00 sec) 2. 测试的表结构信息 mysql>

mysql 索引长度解释及不使用索引的一种特殊情况

如果两个表关联的字段,在表结构中设置的字符集不一样,即使设置了索引,也无法使用. 详情可参考: https://yq.aliyun.com/articles/69138?spm=5176.100239.bloglist.185.xQpesw 关于mysql explain时,key_len字段的计算方法: varchr(10)变长字段且允许NULL    =  10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)varchr(10

mysql设置合适的索引长度

理想的索引: 相对于写操作来说,表查询很频繁的表建立索引 字段区分度高 长度小(合适的长度,不是越小越好) 尽量能够覆盖常用字段 这些条件综合起来才能够达到最优索引,本次我们着重聊一下建立合适长度的索引,索引的长度直接影响索引文件的大小,因此会影响增删改查的速度 给字符类型的字段设置长度字段查询时区分度要高,如果字段只是设置了一个那么回查询很多相似的匹配度不高,长度要恰到好处,否则太长索引文件就会大,因此 要在区分度和长度上做一个平衡. 1.先来看一下没设置索引的查询 mysql> explai

MySQL InnoDB引擎索引长度受限怎么办?

大家应该知道InnoDB单列索引长度不能超过767bytes,联合索引还有一个限制是长度不能超过3072. mysql> CREATE TABLE `tb` ( ->   `a` varchar(255) DEFAULT NULL, ->   `b` varchar(255) DEFAULT NULL, ->   `c` varchar(255) DEFAULT NULL, ->   `d` varchar(255) DEFAULT NULL, ->   `e` var

MySQL索引基本应用[转]

原文地址:http://www.php100.com/html/webkaifa/database/Mysql/2010/0409/4279.html 索引是快速搜索的关键.MySQL索引的建立对于MySQL的高效运行是很重要的.下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表: CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT N