MySQL执行计划里面的key_len

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:   以前看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个字节

0?wx_fmt=png

所以按照这个算法就是4+5=9





相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
SQL 关系型数据库 MySQL
MySQL视图、索引、备份与恢复、执行计划(三)
MySQL视图、索引、备份与恢复、执行计划(三)
39 0
|
4月前
|
关系型数据库 MySQL 数据库
mysq优化---mysql执行计划解释、优化查询、数据库结构、服务器
mysq优化---mysql执行计划解释、优化查询、数据库结构、服务器
|
4月前
|
SQL 算法 关系型数据库
从执行计划了解MySQL优化策略
从执行计划了解MySQL优化策略
54 0
从执行计划了解MySQL优化策略
|
4月前
|
存储 关系型数据库 MySQL
MySQL查询执行计划详解(EXPLAIN)
一、单表查询 访问方法/访问类型: • const:通过主键值或唯一二级索引与一个常熟进行等值查询(不包括NULL),只会生成一条记录 • ref:普通二级索引与一个常数进行等值比较,可能生成多条记录 • ref_or_null:ref的前提下可以加上or key is null • range:对应的扫描区间为若干个单点扫描区间或范围扫描区间(不包括负无穷到正无穷的范围) • index:扫描区间为全表,但是可以在二级索引中扫描(因为二级索引每条记录占用空间更小,所以需要读的页更少) • all:直接扫描全部的聚集索引记录
|
5月前
|
关系型数据库 MySQL 索引
Mysql的执行计划explain
Mysql的执行计划explain
30 0
|
7月前
|
存储 关系型数据库 MySQL
MySQL视图、索引、备份与恢复、执行计划(二)
MySQL视图、索引、备份与恢复、执行计划(二)
49 0
|
7月前
|
存储 关系型数据库 MySQL
MySQL视图、索引、备份与恢复、执行计划(一)
MySQL视图、索引、备份与恢复、执行计划
46 0
|
7月前
|
SQL 存储 关系型数据库
一文读懂 MySQL Explain 执行计划
一文读懂 MySQL Explain 执行计划
113 0
|
8月前
|
存储 关系型数据库 MySQL
MySQL基础应用拓展、索引及执行计划
MySQL基础应用拓展、索引及执行计划
61 0
MySQL基础应用拓展、索引及执行计划
|
8月前
|
SQL 算法 关系型数据库
【MySQL进阶-02】mysql的explain执行计划以及索引优化
【MySQL进阶-02】mysql的explain执行计划以及索引优化
77 0