Mysql-Explain(六):输出列-possiable_keys、key、key_len

简介

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),所以这个字段能分析语句实际用的索引的长度是多少。

猜你喜欢

转载自blog.csdn.net/u012180773/article/details/104333879
今日推荐