MySQL中explain命令详解

explain的作用

我们使用explain命令来查看mysql语句的执行计划(execution plan),解释mysql是如何执行一条sql语句的;解释的内容主要包括表的连接方式和顺序,以及索引的使用情况。使用explain,可以分析出需要在哪里加上索引,以及调整表的连接,以达到优化查询的目的;explain命令之后不仅可以跟select语句,也可以跟delete,insert,update,replace语句。

用法

只需要在sql语句前加上explain就可以了,比如:

+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 100310 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+

如何分析

我们看到explain命令的结果有很多列,通常情况下,我们最关心的指标是select_typetype

概念

Column JSON Name Meaning
id select_id The SELECT identifier(选择标识符)
select_type None The SELECT type(查询类型)
table table_name The table for the output row(结果集使用的表)
partitions partitions The matching partitions(匹配的分区)
type access_type The join type(连接类型)
possible_keys possible_keys The possible indexes to choose(可能使用到的索引)
key key The index actually chosen(实际使用的索引)
key_len key_length The length of the chosen key (使用索引的长度)
ref ref The columns compared to the index(和索引比较的列)
rows rows Estimate of rows to be examined(扫描的行数)
filtered filtered Percentage of rows filtered by table condition(表条件过滤行数的百分比)
Extra None Additional information(附加的信息)

进一步解释

id

id的值越大,执行的优先级越高,id相同,则从上往下顺序执行。所以以下例子:

id placeholder
1 A
1 B
2 C

执行的顺序是:C,A,B。

select_type

select_type Value JSON Name Meaning(含义)
SIMPLE None Simple SELECT (not using UNION or subqueries)(查询查询,不使用union或子查询)
PRIMARY None Outermost SELECT(最外层的select查询)
UNION None Second or later SELECT statement in a UNION (在union中排在第二位甚至更靠后的select语句)
DEPENDENT UNION dependent (true) Second or later SELECT statement in a UNION, dependent on outer query (在union中排在第二位甚至更靠后的select语句,取决于外面的查询)
UNION RESULT union_result Result of a UNION.(union结果集)
SUBQUERY None First SELECT in subquery(子查询中的第一个select)
DEPENDENT SUBQUERY dependent (true) First SELECT in subquery, dependent on outer query(子查询中的第一个select,取决于外面的查询)
DERIVED None Derived table(派生表)
DEPENDENT DERIVED dependent (true) Derived table dependent on another table (派生表,依赖其他表)
MATERIALIZED materialized_from_subquery Materialized subquery (实现子查询)
UNCACHEABLE SUBQUERY cacheable (false) A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query(结果不能被缓存并且外部查询的每一行都必须被重新评估的子查询)
UNCACHEABLE UNION cacheable (false) The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)(在union中排位第二甚至更靠后属于不能缓存的子查询)

table

显示这行的数据是关于哪张表的,也可能是表的别名。

type

可能的取值

null > system > const > eq_ref > ref > range > index > all,从左到右,性能递减,null最好,all最差,一般的,最好能优化查询到const到range之间。

含义

ALL:Full Table Scan,遍历全表。

index: Full Index Scan,index与ALL区别为index类型只遍历索引树,不遍历数据行,所以比all的速度要快。

range: 只检索给定范围的行,这个范围必须应用在一个有索引的列上。

ref: 使用了非唯一索引作为where或join条件,是一个确定的值。

eq_ref: 同ref,但索引是唯一索引。

const、system: 将确定的值应用在索引(unique and not unique)上,type将会是const,当结果只有一行时,typesystem

NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

例子

每一个type都给出了一个例子:

drop table t1, t2, t3;

create table t1 (
  id      int(11) auto_increment,
  name    varchar(50),
  address varchar(100),
  primary key (id),
  key index_name(name)
);
create table t2 (
  id      int(11) auto_increment,
  name    varchar(50),
  address varchar(100),
  primary key (id),
  key index_name(name)
);
create table t3 (
  id      int(11) auto_increment,
  name    varchar(50),
  address varchar(100),
  primary key (id),
  key index_name(name)
);

insert into t1 (name, address)
values ('tom', 'downtown'),
       ('jack', 'country yard');
insert into t2 (name, address)
values ('tom', 'downtown'),
       ('jack', 'country yard');
insert into t3 (name, address)
values ('tom', 'downtown'),
       ('jack', 'country yard');

explain select *
        from t1
        where id = 1; -- const
explain select *
        from t1
        limit 10; -- all
explain select *
        from t1
        where name = 'tom'; -- ref
explain select t1.id
        from t1,
             t2
        where t1.id = t2.id; -- index, eq_ref
explain select t1.*
        from t1,
             t2
        where t1.id = t2.id; -- index, all
explain select *
        from t1
        where id between 1 and 10; -- range
explain select t1.name
        from t1,
             t2
        where t1.name = t2.name; -- index, ref
explain select *
        from t2,
             (select id from t1 where t1.id = 1) t
        where t2.id = t.id;
explain select *
        from (select * from t1 where t1.address = 'downtown') t;
explain select *
        from t1
        where id = 1
        union
        select *
        from t2
        where id = 2; -- const,const,all
explain select *
        from (select * from t1 limit 1) a1; -- system, all

Extra

Using where:不用读取表中所有信息,仅通过索引就可以获取所需数据,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤。

Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by。

Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”。

Using join buffer:该值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。

Impossible where:这个值强调了where语句会导致没有符合条件的行(通过收集统计信息不可能存在结果)。

Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行

No tables used:Query语句中使用from dual 或不含任何from子句。

应用

在很多博客上,都有关于between,>,<,in,not in,like是否会使用索引,如果使用,那么type是什么的文章,其实这个问题的本质是对explain命令的使用,我们只需要写几个包含以上where条件的语句,就可以找到问题的答案了。我们新建一个叫user的表,并且插入10万条随机的英文姓名。测试的结果如下。

create table user (
  id   int(11) auto_increment,
  name varchar(100),
  age  int(11),
  primary key (id),
  key index_age(age),
  key index_name(name)
);

explain select * from user where name in ('tom'); -- use
explain select * from user where name = 'tom'; -- use
explain select * from user where name between 'tom' and 'jerry'; -- not use
explain select * from user where name <> 'tom'; -- not use
explain select * from user where name = 'tom' or name = 'jerry'; -- use
explain select * from user where name like 'om%'; -- use
explain select * from user where name like 'tom'; -- use, 这里的like相当于等号
explain select * from user where name like '%to'; -- not use

explain select * from user where age between 0 and 1; -- use
explain select * from user where age not between 0 and 1; -- not use
explain select * from user where age > 50; -- not use
explain select * from user where age < 50; -- not use
explain select * from user where age != 3; -- not use
explain select * from user where age in (1, 99); -- use
explain select * from user where age = 1 or age = 3; -- use
explain select * from user where age like '1%'; -- not use
explain select * from user where age like '%1'; -- not use

从以上的测试结果,我们可以得出结论:
between and, >,<,in,not in,or,like都是会使用索引的,但是between and, >,<必须用在数值类型的列上;in,not in,or可以用到数值和字符串的列上;而like只能用到字符串类型的列上,而且必须是左边不能以通配符开头。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容