MySQL day9(Explain)

Explain 详解

  • Explain 作用

    • 查看表的读取顺序
    • 数据读取操作的操作类型
    • 查看哪些索引可使用
    • 查看使用使用的索引
    • 查看表之间的引用
    • 查看每张表有多少行被优化器执行
  • Explain 使用方法

    Explain + sql
    e.g.
    	Explain select * from test;
    	
    mysql> explain select * from test;
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
    | id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | test | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | NULL  |
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
  • Explain 字段

    • id: select 查询的序列号, 包含一组数字: 标示查询中执行select自己或者操作表的顺序

      • id 相同, 执行顺序从上往下

        mysql> Explain select * from employee e, department d, customer c where e.dep_id =d.id and e.cus_id = c.id;
        +----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+----------------------------------------------------+
        | id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref           | rows | filtered | Extra                                              |
        +----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+----------------------------------------------------+
        |  1 | SIMPLE      | c     | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL          |    1 |   100.00 | NULL                                               |
        |  1 | SIMPLE      | e     | NULL       | ALL    | NULL          | NULL    | NULL    | NULL          |    8 |    12.50 | Using where; Using join buffer (Block Nested Loop) |
        |  1 | SIMPLE      | d     | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | test.e.dep_id |    1 |   100.00 | NULL                                               |
        +----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+----------------------------------------------------+
        3 rows in set, 1 warning (0.00 sec)
        
      • id 不同: 如果是子查询, id序号会递增, id值越大优先级越高, 优先被执行。

        mysql> explain select * from department where id = (select id from employee where id = (select id from customer where id = 1));
        +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
        | id | select_type | table      | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
        +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
        |  1 | PRIMARY     | department | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL        |
        |  2 | SUBQUERY    | employee   | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
        |  3 | SUBQUERY    | customer   | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
        +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
        3 rows in set, 1 warning (0.00 sec)
        
    • select_type: 查询类型, 主要区别普通查询, 联合查询, 子查询等复杂的查询

      • SIMPLE: 简单的select 查询, 不包含子查询或者union
      mysql> explain select * from department;
        +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
        | id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
       +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
        |  1 | SIMPLE      | department | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | NULL  |
        +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
        1 row in set, 1 warning (0.00 sec)
      
    • PRIMARY: 查询中包含任何的复杂的子查询, 最外层被标记为primary

        mysql> explain select * from employee where dep_id = (select id from department where id = 1);
      +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
        | id | select_type | table      | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
      +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
        |  1 | PRIMARY     | employee   | NULL       | ALL   | NULL          | NULL    | NULL    | NULL  |    8 |    12.50 | Using where |
      |  2 | SUBQUERY    | department | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
        +----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
      2 rows in set, 1 warning (0.00 sec)
      
      • SUBQUERY: 子查询

      • DERIVED: 代表着衍生表(虚拟表), 把结果放在衍生表中

        mysql> explain select * from department d,(select * from(select dep_id from employee group by dep_id) t2 ) t where d.id = t.dep_id;
        +----+-------------+------------+------------+------+---------------+-------------+---------+-----------+------+----------+---------------------------------+
        | id | select_type | table      | partitions | type | possible_keys | key         | key_len | ref       | rows | filtered | Extra                           |
        +----+-------------+------------+------------+------+---------------+-------------+---------+-----------+------+----------+---------------------------------+
        |  1 | PRIMARY     | d          | NULL       | ALL  | PRIMARY       | NULL        | NULL    | NULL      |    5 |   100.00 | NULL                            |
        |  1 | PRIMARY     | <derived3> | NULL       | ref  | <auto_key0>   | <auto_key0> | 5       | test.d.id |    2 |   100.00 | Using index                     |
        |  3 | DERIVED     | employee   | NULL       | ALL  | NULL          | NULL        | NULL    | NULL      |    8 |   100.00 | Using temporary; Using filesort |
        +----+-------------+------------+------------+------+---------------+-------------+---------+-----------+------+----------+---------------------------------+
        3 rows in set, 1 warning (0.00 sec)
        
        
      • UNION: 使用 union

      • UNION RESULT: 使用union , 最后显示的结果集

        mysql> explain select id from department union select id from employee;
        +----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-----------------+
        | id | select_type  | table      | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra           |
        +----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-----------------+
        |  1 | PRIMARY      | department | NULL       | index | NULL          | PRIMARY | 4       | NULL |    5 |   100.00 | Using index     |
        |  2 | UNION        | employee   | NULL       | index | NULL          | PRIMARY | 4       | NULL |    8 |   100.00 | Using index     |
        | NULL | UNION RESULT | <union1,2> | NULL       | ALL   | NULL          | NULL    | NULL    | NULL | NULL |     NULL | Using temporary |
        +----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-----------------+
        3 rows in set, 1 warning (0.03 sec)
        
  • table: 显示这一样查询是关于哪张表的

  • partitions: 如果查询是基于分区表的话,会显示访问的分区

  • type: 访问类型排序(性能从上到下越来越差,)

    • system

      • 表中有一行记录(系统表, 表只有一行MyISAM引擎), 这是 const 类型的特例, 平时不会出现
    • const

      • 表示通过索引一次就找到结果

      • 用于比较 primary 或者 unique 索引。

      • 常量连接,表最多只有一行匹配,通用用于主键或者唯一索引比较时

        mysql> explain select * from employee where id = 1;
        +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
        | id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
        +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
        |  1 | SIMPLE      | employee | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
        +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
        1 row in set, 1 warning (0.00 sec)
        
    • eq_ref

      • 唯一性索引扫描

      • 对于每个索引键, 表中只有一条记录与之匹配

      • 常见于主键或者唯一索引扫描

      • 每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,特点是使用=,而且索引的所有部分都参与join且索引是主键非空唯一键的索引

        mysql> explain select * from employee e, department d where e.id = d.id;
        +----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------+
        | id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref       | rows | filtered | Extra |
        +----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------+
        |  1 | SIMPLE      | d     | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL      |    5 |   100.00 | NULL  |
        |  1 | SIMPLE      | e     | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | test.d.id |    1 |   100.00 | NULL  |
        +----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------+
        2 rows in set, 1 warning (0.00 sec)
        
    • ref

      • 非唯一性索引扫描, 返回匹配某个单独值的所有行
      • 本质上也是一种索引访问
      • 返回所有匹配摸个单独值的行
      • 可能会找到多个符合条件的行
      • 如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键非唯一
    • range

      • 范围查询
    • index

      • 和all 是一种类型, 只不过是扫描了索引树
    • All

      • 扫描全表
  • possible_keys: 可能使用到的索引

  • key: 实际使用的索引

  • ken_len: 表示索引使用的字节数,根据这个值可以判断索引的使用情况,特别是在组合索引的时候,判断该索引有多少部分被使用到非常重要

  • ref: 哪些列或者常量被用做索引列上的值

  • rows: 根据表的统计信息和索引的使用情况,大致估算查询结果所需要读取记录的行数

  • filtered: 表示示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例

  • Extra:

    • using where:

      • SQL使用了where条件过滤数据。(需要借鉴 type 确定效率)
    • Using index:

      • SQL所需要返回的所有列数据均在一棵索引树上,而无需访问实际的行记录(效率高)
    • Using index condition:

      • 确实命中了索引,但不是所有的列数据都在索引树上,还需要访问实际的行记录(效率一般)
    • Using filesort:

      • 得到所需结果集,需要对所有记录进行文件排序(效率低)
    • Using temporary:

      • 需要建立临时表(temporary table)来暂存中间结果(效率低)
    • Using join buffer (Block Nested Loop):

      • 需要进行嵌套循环计算, 即内外层 type 都是 all. (效率低)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值