在日常工作中,我们总会遇到一些SQL查询比较慢的语句,通常我们会使用explain命令来查看执行计划,通过修改SQL语句来达到explain想要的效果,话不多说 我们先来看下explain 的效果
explain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,下来我们来看下各属性的含义
1.id
select 查询的序列号,包含一组数字,查询select字段的执行顺序分为三种情况
如果ID相同:那么执行顺序从上到下
如果ID不同:id值越,执行的优先级越高
如果ID相同和不同同时存在:相同认为一组,组内从上到下执行,在所有组中,ID越大优先级越高
2.select_type
主要用于分辨查询的类型:普通查询、联合查询、子查询。
最好能通过业务拆分来实现简单查询
value | 描述 |
---|---|
SIMPLE | 简单查询 |
PRIMARY | 最外面的查询,在有子查询时,最外面的select就是primary |
UNION | 联合查询 UNION中的第二个或后面的SELECT语句 |
DEPENDENT UNION | UNION中的第二个或后面的SELECT语句,取决于外面的查询 |
UNION RESULT | UNION的结果,union语句中第二个select开始后面所有select |
SUBQUERY | 子查询中的第一个SELECT,结果不依赖于外部查询 |
DEPENDENT SUBQUERY | 子查询中的第一个SELECT,依赖于外部查询 |
DERIVED | 派生表的SELECT, FROM子句的子查询 |
UNCACHEABLE SUBQUERY | 一个子查询的结果不能被缓存,必须重新评估外链接的第一行 |
3.table
对应访问的表名或者别名
如果对应的具体表名或别名:则明确表示从实际的物理表中获取数据
如果表名derivedN 形式:表示使用ID为N查询产生的衍生表
4type
显示的是访问类型,访问类型表示以何种方式访问我们的数据,最容易想到的就是全表扫描,效率非常低下,访问类型有很多,效率从高到低依次是:
system>const>eg_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>range>index>all
一般情况下,需要保证查询至少到range级别,最好到ref
value | 描述 |
---|---|
all | 全表扫描 |
index | 一种是覆盖索引或者使用索引排序 |
range | 表示利用索引查询时限制了范围,避免了索引index全索引扫描 |
index_subquery | 利用索引来关联子查询,不再全表扫描 |
unique_sbuquery | 与index_subquery相似,使用了唯一索引 |
index_merge | 在查询过程中需要多个索引组合使用 |
ref_or_null | 对于某个字段既需要关联条件,也需要null 的情况 |
ref | 使用了非唯一索引进行数据查找 |
eq_ref | 使用了唯一索引进行了数据查找 |
const | 这个表最多有一个匹配 |
system | 表示只有一行记录(等于系统表) 这个是const的特例平时不会出现 |
5.possible_keys
显示可能应用这张表的索引,一个或者多个查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用
6.key
实际使用的索引,如果为null 则没有使用索引
7.key_len
表示索引使用的字节数,可以用key_len 计算查询使用的索引长度,在不损失精度的情况下,越短越好
8.ref
显示索引那一列被使用,如果可能的话,是一个常数(const)
9.row
根据表的统计信息及索引使用情况,大致估算出所需记录,需要读取的行数,此数据很重要,直接反应SQL找了多少条数据,越少越好
10.extra
表示额外信息
value | 描述 |
---|---|
useing filesort | MYSQL手册是这么解释的:“MySQL需要额外的一次传递,以找出如何按排序顺序检索行。通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行。” 说明查询无法利用索引排序,只能利用算法,消耗额外的存储位置,该值最好不要在explain中出现 |
using temporary | 建立临时表保存中间结果,查询完之后删除临时表 |
using index | 使用了覆盖索引,直接从索引中取出数据 |
using where | 使用where条件进行过滤 |
join buffer | 使用连接缓存 |
impossible where | where 语句的结果总是false |