前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL执行计划里面的key_len

MySQL执行计划里面的key_len

作者头像
jeanron100
发布2018-03-21 17:43:48
1.2K0
发布2018-03-21 17:43:48
举报
文章被收录于专栏:杨建荣的学习笔记

以前看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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档