MySQL explain命令实操

explain作用

explain命令是用来查看一个sql语句的执行计划,可以看出这个sql语句是否使用到索引,是否合理可用。

explain返回参数说明

  1. 作用于一个select sql语句:
explain select id from tb_delivery_user_owner where user_id=1;

得到如下图结果:


MySQL explain命令实操_第1张图片
image.png

2.作用于一个update sql:

explain update tb_delivery_user_owner set deleted = 0 where   delivery_user_id=1;
MySQL explain命令实操_第2张图片
image.png

重点解释以下几个字段:

type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般来说,得保证查询至少达到range级别,最好能达到ref。具体说明,如下图:


MySQL explain命令实操_第3张图片
image.png

key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MySQL会选择优化不足的索引。这种情况下,可以在select语句中使用use index(indexname) 来强制使用一个索引或者用ignore index(indexname) 来强制MySQL忽略索引

key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好;也可以根据这个长度判断组合索引是用了部分字段还是所有字段。

ref:显示索引的哪一列被使用了,如果可能的话,是一个常数

rows:预计查询扫描的数据行数

Extra:关于MySQL如何解析查询的附加信息,如下图所示:


MySQL explain命令实操_第4张图片
image.png

explain实操

CREATE TABLE `tb_delivery_user_owner` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `delivery_user_id` int(11) NOT NULL COMMENT '投放账号ID',
  `user_id` int(11) NOT NULL COMMENT '使用者用户ID',
  `deleted` tinyint(1) NOT NULL DEFAULT '0',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_idx_delivery_owner` (`delivery_user_id`,`user_id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='投放账号使用者表';

从建表sql知道表tb_delivery_user_owner有一个组合唯一索引uniq_idx_delivery_owner,索引的第一个字段为delivery_user_id,第二字段为user_id。

  1. 先看第一个sql语句:


    MySQL explain命令实操_第5张图片
    image.png

    显然使用了索引:uniq_idx_delivery_owner,type=const表明基于索引查询,key_len=8说明使用了完整的2个列。

  2. 然后看第二个sql:


    image.png

似乎也用到了索引,但是根据最左匹配原则,user_id作为第二个字段应该用不到索引。这是什么原因呢?最左匹配原则在这里不适用了吗?

解释:这里是使用到索引,但是type=index说明是索引覆盖扫描,需要扫描整个索引表,实际上效果并不好。根据最左匹配原则,user_id不满足,但是它在组合索引列里,所以直接查所有的索引。

接下来看下如果select的列不一样是否有什么不同:


image.png

从图上看到create_time字段不是索引列,当它被select的时候直接就是全表扫描了,这是因为create_time不在索引表中,不能查索引表只能原表扫描。可见查询sql中,除了where条件外select的具体列也会有影响最终执行性能。

总结

  1. explain用于查看sql执行计划,可以分析是否用到索引,便于优化sql
  2. explain的结果除了和where条件有关,还和select的列有关。

你可能感兴趣的:(MySQL explain命令实操)