暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql调优实战利器之explain

不高兴就喝水 2021-07-19
215
mysql有一个explain命令,对我们找到慢SQL后进行分析很有帮助,先通过一个简单的SQL语句来看看有explain哪些东西。通过执行explain select * from user;得到结果集是:

下面的表格是对每一列数据的介绍信息。

结果列

介绍

id

执行语句的标记,记住两种情况即可:

1、id一样时,按顺序从上往下执行

2、id不一样,id大的先执行

select_type

表示对应查询的语句类型

1、simple 简单查询

2、primary 复杂查询中最外层的select

3、subquery 包含在select中的子查询

4、derived 派生表

5、union union用法后的查询

table

代表当前查询的表,如果有子查询,显示的是derived<id>

type

表示访问的类型,按性能来分,最优到最差的排序为:system>const>eq_ref>ref>range>index>ALL

system,const:可以将部分查询转换成常量的查询,速度很快,用于primary key 或unique key的列和常数进行比较,最多只有一条数据。system是const的特例,代表表里只有一条数据时为system

eq_ref:primary key 或unique key用于关联查询时,可能出现

ref: 使用普通索引时的类型(或者唯一索引的部分信息,比如使用联合主键时使用了头字段的情况)

range:范围扫描时出现

index:扫描全索引获取结果(一般指扫描的二级索引)

ALL:全表扫描

possible_keys

表示可能会用到的索引信息

key

显示使用哪个索引来进行查询

可能出现possible_keys有值但key为NULL的情况,这代表mysql内部认为使用索引可能效果不如全表查询

key_len

表示mysql在索引里用到的字节数,一般根据索引字段的字节长度计算

ref

显示表查找值所用到的列或者常量

rows

执行sql估计要读取的行数

extra

展示一些额外信息说明

1、Using index :表示使用覆盖索引,只使用索引就可拿到结构,不用回表

2、Using where:表示使用where语句处理结果,查询的列未被索引覆盖

3、Using index condition:使用了索引,还需要回表

4、Using temporary:需要使用一张临时表来处理查询,一般需要进行优化

5、Using filesort:排序中出现,且排序字段不在索引覆盖范围内


然后呢,我们使用一些SQL对这些字段属性做更进一步的认识。

    CREATE TABLE `user` (
    `id` int(11) NOT NULL,
    `name` varchar(45) DEFAULT NULL,
    `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    INSERT INTO `user` (`id`, `name`) VALUES (1,'a'), (2,'b'), (3,'c');


    DROP TABLE IF EXISTS `job`;
    CREATE TABLE `job` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(10) DEFAULT NULL,
    `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_name` (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    INSERT INTO `job` (`id`, `name`) VALUES (3,'job3'),(1,'film1'),(2,'film2');


    DROP TABLE IF EXISTS `user_job`;
    CREATE TABLE `user_job` (
    `id` int(11) NOT NULL,
    `job_id` int(11) NOT NULL,
    `user_id` int(11) NOT NULL,
    `remark` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `idx_user_job_id` (`job_id`,`user_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    INSERT INTO `user_job` (`id`, `job_id`, `user_id`) VALUES (1,1,1),(2,1,2),(3,2,1);

    首先,创建几张表供我们使用,然后我们用一些执行语句来进行分析。

    1、select_type及table分析语句

      set session optimizer_switch='derived_merge=off';
      explain select (select 1 from user where id = 1) from (select * from job where id = 1) der ;

      从上面的例子,我们可以看到DERIVED是我们从job中查出数据的衍生表 ,SUBQUERY是一个子查询(select 1 from user where id = 1),PRIMARY是最外层的表信息,使用的表是派生表<derived3>

      2、type分析语句

        explain select * from (select * from job where id = 1) der ;


        这里我们关注类型,const类型的是id=1的派生表的查询情况,用于主键的查询且查询数据只有一条的情况,system是因为派生表里就一条数据(也就是刚刚查出来的id=1的那条),所以类型是system,可以看做const的特例。


          explain select * from user_job left join job on user_job.job_id = job.id;

          看eq_ref类型的数据,使用了主键索引进行关联查询出现,每次最多只返回一条符合的记录。


            explain select * from job where name = 'job1';
            explain select * from job where name like 'job%';

            差不多的两条sql,一个是直接找一个值,一个是范围的查询,都使用了同一个索引idx_name,我们可以根据type区别出,ref的是普通索引的查询,range是范围查询


              explain select idname from job;

              这里我们可以看到,查询job的id和name时,type是index而不是ALL,由于我们对name建立了索引,扫描二级索引就能得到想要的id和name的结果,所以就是index,如果没有这个索引或者再多查询一个字段,那就会变成ALL。比如:explain select id, name,create_time from job;

              结果就变成了了ALL。

              PS:一般来说,我们要尽量的去避免全局扫描,也就是type=ALL的情况。


              3、extra分析

              我们再来关注Extra列,上面的几个explain查询里面有些Extra是空的,有些里面有Using index。

              那这个SQL的结果来说(explain select id, name from job)

              我们可以发现他们都使用了索引,并且不需要再去主键索引里找数据就能得到最终的结果。
              再看这句explain select * from user where name = 'a';

              name没有放置索引,符合Using where的描述。


              我们再看两组排序的对比,
                explain select id , name from user ORDER BY name;


                  explain select id , name from job ORDER BY name;

                  一个是Using filesort , 一个是Using index ,当我们有二级索引且运用上的时候,数据库会帮我们尽量的去使用索引,而没有二级的索引的使用的是外部排序。
                  结合以上的分析来说,我们要优化一个SQL,那么第一个想到的就是让该走索引的都尽量走索引哦。


                  文章转载自不高兴就喝水,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论