mysql 索引长度限制详解

mysql 每个单表中对索引长度是有限制的,且根据不同的数据引擎会有所不同。
下面以mysql 5.5.47 版本为例做相应的说明。

MYISAM表
1、创建一个字符编码为utf8的表 test
create table test(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500)) CHARSET=utf8 engine=myisam;

然后创建组合索引
create index list on test(name1,name2,name3);
这个时候会报
[Err] 1071 - Specified key was too long; max key length is 1000 bytes
索引没有创建成功,因为三列长度总和300+300+500超过了1000字节,所以报错。
在name2上创建索引
create index name2 on test(name2)
创建成功

CREATE TABLE `test` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `name2` (`name2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

在name3上 创建索引
create index name3 on test(name3)

CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `name1` varchar(1) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name3` (`name3`(333)),
  KEY `name2` (`name2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

创建索引成功但长度被截取为name3(333)。

2、创建一个字符编码为latin1 的表 test1
create table test1(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500)) CHARSET=latin1 engine=myisam;

然后创建组合索引
create index list on test1(name1,name2,name3);
报错:[SQL]create index list on test1(name1,name2,name3);
[Err] 1071 - Specified key was too long; max key length is 1000 bytes
创建索引失败

在name2 创建索引
create index name2 on test1(name2)

CREATE TABLE `test1` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `name2` (`name2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

创建成功
在name3上 创建索引
create index name3 on test1(name3)

CREATE TABLE `test1` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `name3` (`name3`),
  KEY `name2` (`name2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

删除name3索引
drop index name3 on test1;
增加name2 宽度为1500
ALTER TABLE test1 MODIFY name3 VARCHAR(1500);

在name3上 创建索引
create index name3 on test1(name3)

CREATE TABLE `test1` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(1500) DEFAULT NULL,
  KEY `name2` (`name2`),
  KEY `name3` (`name3`(1000))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

创建索引成功但长度被截取为name3(1000)。

InnoDB表

1、创建一个字符编码为utf8的表 test 3
create table test3(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500)) CHARSET=utf8 engine=InnoDB;

然后创建组合索引
create index list on test3(name1,name2,name3);

CREATE TABLE `test3` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`(255),`name2`(255),`name3`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建成功,索引为 KEY list (name1(255),name2(255),name3(255))

在name2 创建索引
create index name2 on test3(name2)

CREATE TABLE `test3` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`(255),`name2`(255),`name3`(255)),
  KEY `name2` (`name2`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

索引为 KEY name2 (name2(255))

在name3上 创建索引
create index name3 on test3(name3)

CREATE TABLE `test3` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`(255),`name2`(255),`name3`(255)),
  KEY `name2` (`name2`(255)),
  KEY `name3` (`name3`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

索引为KEY name3 (name3(255))

2、创建一个字符编码为latin1 的表 test4
create table test4(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500)) CHARSET=latin1 engine=InnoDB;

然后创建组合索引
create index list on test4(name1,name2,name3);

创建成功

CREATE TABLE `test4` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`,`name2`,`name3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

在name2 创建索引
create index name2 on test4(name2)

CREATE TABLE `test4` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`,`name2`,`name3`),
  KEY `name2` (`name2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

索引为 KEY name2 (name2)

在name3 创建索引
create index name3 on test4(name3)

CREATE TABLE `test4` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(500) DEFAULT NULL,
  KEY `list` (`name1`,`name2`,`name3`),
  KEY `name2` (`name2`),
  KEY `name3` (`name3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

修改name3的宽度为1000
ALTER TABLE test4 MODIFY name3 VARCHAR(1000);
在查看表的信息

CREATE TABLE `test4` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(300) DEFAULT NULL,
  `name2` varchar(300) DEFAULT NULL,
  `name3` varchar(1000) DEFAULT NULL,
  KEY `list` (`name1`,`name2`,`name3`(767)),
  KEY `name2` (`name2`),
  KEY `name3` (`name3`(767))
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

索引变为 KEY list (name1,name2,name3(767)),
KEY name2 (name2),
KEY name3 (name3(767))

总结

1、对于myisam表,组合索引的长度跟各个列总和长度有关。
字符编码为utf8,组合索引长度和不能超333,超过则创建失败。单列索引不能超过333,如果字段超过333,则最终创建的是前缀索引(即取前333个字节)。
字符编码为latin1,组合索引长度和不能超1000,超过则创建失败。单列索引不能超过1000,超过则最终创建的是前缀索引(即取前1000个字节)。
2、对于Innodb表,组合索引的长度跟各列的长度和无关,跟单列的长度有关,且能创建成功。
字符编码为utf8,组合索引长度最大为:列数*255( name1(255),name2(255),name3(255)),单列索引长度最大为255。
字符编码为latin1,组合索引长度最大为:列数*767(例如:name1,name2,name3(767)),单列索引最大为767。
3、索引的长度跟数据引擎有关,还和字符编码有关。

参考:https://dev.mysql.com/doc/refman/5.7/en/create-index.html

你可能感兴趣的:(mysql)