MySQL innodb的组合索引各个列中的长度不能超过767,
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字节)。
一、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。
三、使用前缀索引带来的风险:
- 索引覆盖扫描
- 通过索引的排序(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,的更多相关文章
- MySQL InnoDB表和索引之聚簇索引与第二索引
MySQL InnoDB表和索引之聚簇索引与第二索引 By:授客QQ:1033553122 每个InnoDB表都有一个称之为聚簇索引(clustered index)的特殊索引,存储记录行数据.通常, ...
- 搞懂MySQL InnoDB B+树索引
一.InnoDB索引 InnoDB支持以下几种索引: B+树索引 全文索引 哈希索引 本文将着重介绍B+树索引.其他两个全文索引和哈希索引只是做简单介绍一笔带过. 哈希索引是自适应的,也就是说这个不能 ...
- mysql 允许在唯一索引的字段中出现多个null值
线上问题:org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [update fl_table ...
- MySQL -- Innodb是如何处理自增列的
对于那些向带有自增列的表中插入行的语句,Innodb提供一种可配置的锁定机制,这种锁定机制可以显著提高SQL语句的可伸缩性和性能. Innodb中为了使用自增机制,自增列必须是索引的部份,从而可以使用 ...
- mysql InnoDb存储引擎索引
B+树索引:使用B+树索引查找数据时,并不能找到一个给定键值的具体行,只是找到被查找数据行所在的页,然后数据库通过把页读取到内存,再在内存中进行查找,最后得到要查找的数据. 聚集索引:按照表中主键构造 ...
- mysql组合索引的有序性<转>
昨天同事关于军规里的一条mysql索引的问题咨询我,才发现自己也不太了解组合索引的规则.于是来记录一下: [推荐]如果有order by的场景,请注意利用索引的有序性.order by 最后的字段是组 ...
- mysql innodb存储引擎的聚集索引
InnoDB聚集索引 MySQL有没有支持聚集索引,取决于采用哪种存储引擎. MySQL InnoDB一定会建立聚集索引,所谓聚集,指实际数据行和相关的键值保存在一块,这也决定了一个表只能有一个聚集索 ...
- sql server中使用组合索引需要注意的地方
一.使用组合索引需要注意的地方 1.索引应该建在选择性高的字段上(键值唯一的记录数/总记录条数),选择性越高索引的效果越好.价值越大,唯一索引的选择性最高: 2.组合索引中字段的顺序,选择性越高的字段 ...
- MYSQL查询优化:使用索引
索引是提高查询速度的最重要的工具.当然还有其它的一些技术可供使用,但是一 般来说引起最大性能差异的都是索引的正确使用.在MySQL邮件列表中,人们经常询问那些让查询运行得更快的方法.在大多数情况下,我 ...
随机推荐
- 【ABAP系列】SAP ABAP ALV中的TOP_OF_PAGE添加任意图标
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP ABAP ALV中的TOP_ ...
- Arduino的小灯亮起来~~~
呵呵呵~~~昨天宝宝,就守着板子,跟说明书,心里默念,怎么特么还不亮?这个 东西怎么还不出!?~ 我特么没插线,可不不出么... 然后找那跟儿蓝色(我这个是蓝色的,不知道 有没有别的颜色的)的带USB ...
- State Function Approximation: Linear Function
In the previous posts, we use different techniques to build and keep updating State-Action tables. B ...
- 手把手教你用Pytorch-Transformers——实战(二)
本文是<手把手教你用Pytorch-Transformers>的第二篇,主要讲实战 手把手教你用Pytorch-Transformers——部分源码解读及相关说明(一) 使用 PyTorc ...
- 极*Java速成教程 - (2)
Java语言基础 Java的一切都是以对象为基础,对象是生是死的生命周期由虚拟机管理,但是在创生和消亡阶段,需要我们去管理这个类怎么生,怎么死.我们也以此为契机,慢慢接触Java的诸多细节和具体实现. ...
- 初学css 行内元素与块级元素
行内元素与块级元素直观上的区别 1.行内元素会在一条直线上排列,都是同一行的,水平方向排列块级元素各占据一行,垂直方向排列.块级元素从新行开始结束接着一个断行. 2.块级元素可以包含行内元素和块级元素 ...
- spring-security问题记录
一.错误信息 Could not decode JSON for additional information: BaseClientDetails 2019-12-03 22:18:37.239 W ...
- Dubbo源码学习总结系列七---注册中心
Dubbo注册中心是框架的核心模块,提供了服务注册发现(包括服务提供者.消费者.路由策略.覆盖规则)的功能,该功能集中体现了服务治理的特性.该模块结合Cluster模块实现了集群服务.Dubbo管理控 ...
- 【LeetCode】数学(共106题)
[2]Add Two Numbers (2018年12月23日,review) 链表的高精度加法. 题解:链表专题:https://www.cnblogs.com/zhangwanying/p/979 ...
- 3.xml的解析
1.xml的解析原理简介(xml是标记型文档) (1)js使用dom解析标记型文档(html)? - 根据html的层级结构,在内存中分配一个树形结构,把html的标签,属性和文本都封装成对象 - d ...