Mysql-Explain(六):输出列-possiable_keys、key、key_len
Mysql-Explain(一):explain简介和输出列解释
Mysql-Explain(二):explain实验数据准备
Mysql-Explain(三):输出列-id
Mysql-Explain(四):输出列-select_type
Mysql-Explain(五):输出列-type
Mysql-Explain(六):输出列-possiable_keys、key、key_len
Mysql-Explain(七):输出列-ref、rows
Mysql-Explain(八):输出列-extra
简介
possiable_keys | 显示可能应用在这张表中的索引,一个或者多个,查询的涉及的字段若存在索引,则该索引被列出,但是不一定被查询实际用到 | ||
key | 实际使用的索引,如果为NULL,则没有使用索引;若查询中使用了覆盖索引,则该索引只会出现在key列表中 | ||
key_len | 表示索引中使用的字节数,可通过该列计算查询中所使用索引的长度,在损失精度的情况下,索引长度越短越好;key_len显示的值为索引字段最大的可能长度,并非实际使用的长度,即key_len是根据表的定义计算而得,并非通过表内检索出的 |
演示
-
possiable_keys:可能会使用到的索引;key:实际会使用到的索引
mysql> alter table student -> add index ik_schoolId_majorId using btree (school_id asc,major_id asc) -> ,add index ik_majorId using btree (major_id); Query OK, 0 rows affected (27.30 sec) Records: 0 Duplicates: 0 Warnings: 0
首先创建两个辅助索引:ik_schoolId_majorId、ik_majorId
mysql> explain select * from student where school_id = 3 and major_id < 1; +----+-------------+---------+------------+-------+--------------------------------+---------------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+-------+--------------------------------+---------------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | student | NULL | range | ik_schoolId_majorId,ik_majorId | ik_schoolId_majorId | 10 | NULL | 5 | 100.00 | Using index condition | +----+-------------+---------+------------+-------+--------------------------------+---------------------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
possiable_keys显示可能会使用的索引有两个:ik_schoolId_majorId,ik_majorId,而key显示实际用到的索 引是 ik_schoolId_majorId。
mysql> explain select id,school_id,major_id from student; +----+-------------+---------+------------+-------+---------------+---------------------+---------+------+---------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+-------+---------------+---------------------+---------+------+---------+----------+-------------+ | 1 | SIMPLE | student | NULL | index | NULL | ik_schoolId_majorId | 10 | NULL | 1800825 | 100.00 | Using index | +----+-------------+---------+------------+-------+---------------+---------------------+---------+------+---------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
如果查询用到的是覆盖索引,并且没有where查询条件,key会显示实际用到的索引,但是possiable_keys不会显示。
-
key_len:实际使用的索引字节长度,可以分为变长和定长数据类型两种。
1、当索引字段为定长数据类型时,如char,int,datetime,需要有是否为空的标记,这个标记占用1个字节(对于not null的字段来说,则不需要这1字节)。
mysql> explain select * from student where major_id = 1; +----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | student | NULL | ref | ik_majorId | ik_majorId | 5 | const | 4027 | 100.00 | NULL | +----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
索引ik_majorId只包含一个字段major_id(int类型,可以为null),所以key_len=4+1,其中int类型占4个字节,一个字节空标记。
2、当索引字段为变长数据类型,比如varchar,除了是否为空的标记外,还需要有长度信息,需要占用两个字节。
mysql> explain select * from student where name like 'N%'; +----+-------------+---------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------------+ | 1 | SIMPLE | student | NULL | range | ik_name | ik_name | 51 | NULL | 161400 | 100.00 | Using index condition | +----+-------------+---------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------------+ 1 row in set, 1 warning (0.02 sec)
索引ik_name主包含一个字段name(varchar(12)),所以key_len=12 * 4 + 2 + 1=51,其中12*4是因为表student使用的uft-8mb4编码,每个字符占用4个字节,2个字节记录变长数据类型的长度信息,一个字节是空标记。
3、key_len表示的是索引实际使用的长度,并不是索引本身所有索引列的长度总和
mysql> explain select * from student where school_id = 1; +----+-------------+---------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | student | NULL | ref | ik_schoolId_majorId | ik_schoolId_majorId | 5 | const | 1960 | 100.00 | NULL | +----+-------------+---------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
复合索引ik_schoolId_majorId有两个字段,shcool_id(int,可以为空),major_id(int,可以为空),按照上面两点的计算方法,该索引的长度是(4+1)+(4+1)。不过explain的返回里key_len显示的是5,那是因为上面的Sql语句只用到了索引ik_schoolId_majorId的第一个字段school_id,因此是5不是10.
mysql> explain select * from student where name like 'abcdefghijklnnopq%'; +----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | student | NULL | range | ik_name | ik_name | 51 | NULL | 1 | 100.00 | Using index condition | +----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
上面语句中’abcdefghijklnnopq%'的字符长度是17,但是key_len的长度是51,表示只用到了前12个字符,因为name字段是varcher(12),所以这个字段能分析语句实际用的索引的长度是多少。