MySQL索引的索引长度问题

 

  MySQL的每个单表中所创建的索引长度是有限制的,且对不同存储引擎下的表有不同的限制。
  在MyISAM表中,创建组合索引时,创建的索引长度不能超过1000,注意这里索引的长度的计算是根据表字段设定的长度来标量的,例如:
create table test(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500))charset=latin1 engine=myisam;
create index test_name on test(name1,name2,name3);
  此时报错:Specified key was too long;max key length is 1000 bytes.

  修改表结构:alter table test convert to charset utf8;
  create index test_name3 on test(name3).
  此时warning:Specified key was too long;max key length is 1000 bytes.但是索引创建成功,查看表结构可以看到创建的索引是一个前缀索引:‘key test_name3(name3(333))’

  得出的结论是:对于myisam表,如果创建组合索引,所创建的索引长度和不能超过1000 bytes,否则会报错,创建失败;对于myisam的单列索引,最大长度也不能超过1000,否则会报警,但是创建成功,最终创建的是前缀索引(取前333个字节)。

  在Innodb表中,创建组合索引:
  create table test1(id int,name1 varchar(300),name2 varchar(300),name3 varchar(500))charset=latin1 engine=innodb;
  create index test1_name on test(name1,name2,name3);
  此时给出warning:Specified key was too long;max key length is 767 bytes.

  修改表结构:alter table test1 convert to charset utf8;
  create index test1_name3 on test(name3).
  此时给出warning:Specified key was too long;max key length is 767 bytes.

  得出的结论是:对于创建innodb的组合索引,如果各个列中的长度不超过767,则不再计算所有列的总长度,如果有超过767的,则给出报警,索引最后创建成功,但是对于超过767字节的列取前缀索引;对于innodb的单列索引,超过767的,给出warning,最终索引创建成功,取前缀索引(取前255字节)。

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> show create table tb2\G
*************************** 1. row ***************************
Table: tb2
Create Table: CREATE TABLE `tb2` (
`a` varchar(255) DEFAULT NULL,
`b` varchar(255) DEFAULT NULL,
`c` varchar(255) DEFAULT NULL,
`d` varchar(1000) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

3. 测试加索引

(1)添加单列索引,能够添加成功(报出warning),但实际添加的是前缀索引。

mysql> alter table tb2 add index idx1 (d);
Query OK, 0 rows affected, 2 warnings (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show warnings;
+---------+------+----------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------+
| Warning | 1071 | Specified key was too long; max key length is 1000 bytes |
| Warning | 1071 | Specified key was too long; max key length is 1000 bytes |
+---------+------+----------------------------------------------------------+
2 rows in set (0.00 sec)

表结构信息:

mysql> show create table tb2\G
*************************** 1. row ***************************
Table: tb2
Create Table: CREATE TABLE `tb2` (
`a` varchar(255) DEFAULT NULL,
`b` varchar(255) DEFAULT NULL,
`c` varchar(255) DEFAULT NULL,
`d` varchar(1000) DEFAULT NULL,
KEY `idx1` (`d`(333))
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

(2)添加组合索引,会执行失败。

mysql> alter table tb2 add index idx1 (a,b);
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes

4. 分析

myisam存储引擎在创建索引的时候,索引键长度是有一个较为严格的长度限制的,所有索引键最大长度总和不能超过1000,而且不是实际数据长度的总和,而是索引键字段定义长度的总和。

主要字符集的计算方式:
latin1 = 1 byte = 1 character
uft8 = 3 byte = 1 character
gbk = 2 byte = 1 character

二、innodb存储引擎

1. 表结构信息:

mysql> create table tb1 (a varchar(255), b varchar(255), c varchar(255), d varchar(1000));
Query OK, 0 rows affected (0.01 sec)

2. 添加组合索引,报出waring,实际在某个单列上添加的是前缀索引

mysql> alter table tb1 add index idx1(a,b,c,d);

Query OK, 0 rows affected, 2 warnings (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show warnings;
+---------+------+---------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------+
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
+---------+------+---------------------------------------------------------+
2 rows in set (0.00 sec)

3. 添加单列索引,报出waring,实际添加的是前缀索引

mysql> alter table tb1 add index idx2(d);
Query OK, 0 rows affected, 2 warnings (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show warnings;
+---------+------+---------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------+
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
+---------+------+---------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> show create table tb1\G
*************************** 1. row ***************************
Table: tb1
Create Table: CREATE TABLE `tb1` (
`a` varchar(255) DEFAULT NULL,
`b` varchar(255) DEFAULT NULL,
`c` varchar(255) DEFAULT NULL,
`d` varchar(1000) DEFAULT NULL,
KEY `idx1` (`a`,`b`,`c`,`d`(255)),
KEY `idx2` (`d`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

4. 分析:

默认情况下,InnoDB 引擎单一字段索引的长度最大为 767 字节,同样的,前缀索引也有同样的限制。当使用 UTF-8 字符集,每一个字符使用 3 字节来存储,在 TEXT 或者 VARCHAR 类型的字段上建立一个超过 255 字符数的前缀索引时就会遇到问题。可以启用服务器选项 innodb_large_prefix 使得这个限制增加到 3072 字节,而且表的 row_format 需要使用 compressed 或者 dynamic。

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

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

还是在上面的测试表上:

mysql> explain select * from tb1 order by d;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | tb1 | ALL | NULL | NULL | NULL | NULL | 5 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> explain select * from tb1 group by d;
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | SIMPLE | tb1 | ALL | NULL | NULL | NULL | NULL | 5 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
1 row in set (0.00 sec)

MySQL innodb的组合索引各个列中的长度不能超过767,的更多相关文章

  1. MySQL InnoDB表和索引之聚簇索引与第二索引

    MySQL InnoDB表和索引之聚簇索引与第二索引 By:授客QQ:1033553122 每个InnoDB表都有一个称之为聚簇索引(clustered index)的特殊索引,存储记录行数据.通常, ...

  2. 搞懂MySQL InnoDB B+树索引

    一.InnoDB索引 InnoDB支持以下几种索引: B+树索引 全文索引 哈希索引 本文将着重介绍B+树索引.其他两个全文索引和哈希索引只是做简单介绍一笔带过. 哈希索引是自适应的,也就是说这个不能 ...

  3. mysql 允许在唯一索引的字段中出现多个null值

    线上问题:org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [update fl_table ...

  4. MySQL -- Innodb是如何处理自增列的

    对于那些向带有自增列的表中插入行的语句,Innodb提供一种可配置的锁定机制,这种锁定机制可以显著提高SQL语句的可伸缩性和性能. Innodb中为了使用自增机制,自增列必须是索引的部份,从而可以使用 ...

  5. mysql InnoDb存储引擎索引

    B+树索引:使用B+树索引查找数据时,并不能找到一个给定键值的具体行,只是找到被查找数据行所在的页,然后数据库通过把页读取到内存,再在内存中进行查找,最后得到要查找的数据. 聚集索引:按照表中主键构造 ...

  6. mysql组合索引的有序性<转>

    昨天同事关于军规里的一条mysql索引的问题咨询我,才发现自己也不太了解组合索引的规则.于是来记录一下: [推荐]如果有order by的场景,请注意利用索引的有序性.order by 最后的字段是组 ...

  7. mysql innodb存储引擎的聚集索引

    InnoDB聚集索引 MySQL有没有支持聚集索引,取决于采用哪种存储引擎. MySQL InnoDB一定会建立聚集索引,所谓聚集,指实际数据行和相关的键值保存在一块,这也决定了一个表只能有一个聚集索 ...

  8. sql server中使用组合索引需要注意的地方

    一.使用组合索引需要注意的地方 1.索引应该建在选择性高的字段上(键值唯一的记录数/总记录条数),选择性越高索引的效果越好.价值越大,唯一索引的选择性最高: 2.组合索引中字段的顺序,选择性越高的字段 ...

  9. MYSQL查询优化:使用索引

    索引是提高查询速度的最重要的工具.当然还有其它的一些技术可供使用,但是一 般来说引起最大性能差异的都是索引的正确使用.在MySQL邮件列表中,人们经常询问那些让查询运行得更快的方法.在大多数情况下,我 ...

随机推荐

  1. spring-data-elasticsearch使用出现的一些小问题

    问题一failed to load elasticsearch nodes : org.elasticsearch.index.mapper.MapperParsingException: No ty ...

  2. elementUi--->实现上传图片效果(upload+formData)

    现在谈一下elelmentui中使用Upload 上传通过点击或者拖拽上传文件(图片) <el-upload name="multfile"    //上传的文件字段名 cl ...

  3. Smashing Nodejs 读书笔记(二)

    了不起的Node.js:将JavaScript进行到底 书名:SMASHING Node.js : JavaScript Everywhere 原作者:(美)劳奇 Rauch.G 译者:赵静 出版日期 ...

  4. [Python3 练习] 009 利用列表隐藏并找到有用的信息

    题目:利用列表隐藏并找到有用的信息 (1) 描述 1) 题源 鱼 C 论坛中"小甲鱼"老师出的题 链接地址:第020讲:函数:内嵌函数和闭包 | 课后测试题及答案 2) 修改 题中 ...

  5. zend studio远程自动上传代码并执行

    http://devzc.com/archives/382/zend_studio_sftp_upload_and_exec/ 最近要做服务的接口测试,公司原有的ide测试工具对于数组的参数化很弱.由 ...

  6. hibernate的get方法和load方法区别

    读者需注意:Hibernate版本不同,运行机制不太一样,以下是hibernate3.x作为讲解 get方法: Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然 ...

  7. 洛谷 P1462 通往奥格瑞玛的道路(二分答案,堆优化dijkstra)

    传送门 解题思路 首先看题目问题,求经过的所有城市中最多的一次收取的费用的最小值是多少.一看“最大值最小”就想到了二分答案. 在读一遍题目,就是二分收取的费用,然后对于每一个二分的费用,跑一边最短路, ...

  8. Educational Codeforces Round 60 (Rated for Div. 2) D. Magic Gems(矩阵快速幂)

    题目传送门 题意: 一个魔法水晶可以分裂成m个水晶,求放满n个水晶的方案数(mol1e9+7) 思路: 线性dp,dp[i]=dp[i]+dp[i-m]; 由于n到1e18,所以要用到矩阵快速幂优化 ...

  9. pg_restore - 从一个由 pg_dump 创建的备份文件中恢复 PostgreSQL 数据库。

    SYNOPSIS pg_restore [ option...] [ filename] DESCRIPTION 描述 pg_restore 是一种用于恢复由 pg_dump(1) 创建的任何非纯文本 ...

  10. 转载——CentOS---网络配置详解

    看到一篇关于Centos网络配置很详细的文章,特此复制来.原文网址:http://blog.chinaunix.net/uid-26495963-id-3230810.html 一.配置文件详解在RH ...