这篇文章主要介绍了MySQL执行计划里面的key_len有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
以前看MySQL的执行计划,感觉内容有些简陋,平时分析主要就是看是否全表扫描,索引使用是否合理等。基本上也能分析出很多问题来,但是显然有时候会有些疑惑,那就是对于复合索引,多列值的情况下,到底启用了那些索引列,这个时候索引的使用情况就很值得琢磨琢磨了,我们得根据执行计划里面的key_len做一个重要的参考。
我们做一个简单的测试来说明。
CREATE TABLE `department` (
`DepartmentID` int(11) DEFAULT NULL,
`DepartmentName` varchar(20) DEFAULT NULL,
KEY `IND_D` (`DepartmentID`),
KEY `IND_DN` (`DepartmentName`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
运行语句为:explain select count(*)from department\G
对于这个语句,key_len到底是多少呢?
mysql> explain select count(*)from department\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: department
type: index
possible_keys: NULL
key: IND_D
key_len: 5
ref: NULL
rows: 1
Extra: Using index
1 row in set (0.00 sec)
在这个例子里面,possible_keys,key,Extra你看了可能有些晕,我们看看key_len的值为5,这个值是怎么算出来的呢,首先表有两个字段,第一个字段的类型为数值,int的长度为4,因为字段可为null,所以需要一个字节来存储,这样下来就是4+1=5了。由此我们可以看到这个语句是启用了索引ind_d.
那我们举一反三,把语句修改一下,看看key_len的变化。
mysql> explain select departmentName from department b where departmentName='TEST'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: b
type: ref
possible_keys: IND_DN
key: IND_DN
key_len: 43
ref: const
rows: 1
Extra: Using where; Using index
1 row in set (0.09 sec)
从上面可以看到,key_len为43,这个值是怎么算出来的呢,我们来掰扯一下,字段2为字符型,长度20,因为是GBK字符集,所以需要乘以2,因为允许字段为NULL,则需要一个字节,对于变长的类型(在此就是VARCHAR),key_len还要加2字节。这样下来就是20*2+1+2=43
到了这里仅仅是个开始,我们需要看看略微复杂的情况,就需要复合索引了。我们就换一个表test_keylen2
create table test_keylen2 (c1 int not null,c2 int not null,c3 int not null);
alter table test_keylen2 add key idx1(c1, c2, c3);
下面的语句就很实际了,
explain SELECT *from test_keylen2 WHERE c1=1 AND c2=1 ORDER BY c1\G
这个语句中,keylen到底是应该为4或者8还是12呢? 我们就需要验证一下了。
mysql> explain SELECT *from test_keylen2 WHERE c1=1 AND c2=1 ORDER BY c1\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test_keylen2
type: ref
possible_keys: idx1
key: idx1
key_len: 8
ref: const,const
rows: 1
Extra: Using index
1 row in set (0.07 sec)
显然key_len只计算了where中涉及的列,因为是数值类型,所以就是4+4=8
那下面的这个语句呢。
explain SELECT *from test_keylen2 WHERE c1>=1 and c2=2 \G
我们添加一个范围,看看这个该如何拆分。
mysql> explain SELECT *from test_keylen2 WHERE c1>=1 and c2=2 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test_keylen2
type: index
possible_keys: idx1
key: idx1
key_len: 12
ref: NULL
rows: 1
Extra: Using where; Using index
1 row in set (0.07 sec)
在这里就不只是计算where中的列了,而是因为>1的条件直接选择了3个列来计算。
对于date类型的处理,有一个很细小的差别。我们再换一个表,含有事件类型的字段,
CREATE TABLE `tmp_users` (
`id` int(11) NOT NULL
AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`l_date` datetime NOT NULL,
`data` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ind_uidldate` (`uid`,`l_date`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
下面的语句key_len该如何计算呢。
explain select * from tmp_users where uid = 9527 and l_date >= '2012-12-10 10:13:17'\G
这一点出乎我的意料,按照datetime的印象是8个字节,所以应该是8+4=12,但是这里却偏偏是9,这个数字怎么计算的。
id: 1
select_type: SIMPLE
table: tmp_users
type: range
possible_keys: ind_uidldate
key: ind_uidldate
key_len: 9
ref: NULL
rows: 1
Extra: Using index condition
1 row in set (0.07 sec)
这里就涉及到一个技术细节,是在MySQL 5.6中的datetime的存储差别。在5.6.4以前是8个字节,之后是5个字节
所以按照这个算法就是4+5=9
感谢你能够认真阅读完这篇文章,希望小编分享的“MySQL执行计划里面的key_len有什么用”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!