mysql中确定sql是否需要优化的方式很多,常见的就是看sql的执行时间,一般的sql执行的正常查询时间是在毫秒级,几十毫秒或是几百毫秒(数据在千万级别的除外,暂时没有处理过此处不做讨论),执行时间超过此时间段的就需要进行优化了。另一种最常见的就是看mysql的执行计划。这也是本文的重点说明的内容,将具体讲述执行计划中每个字段的含义。
explain执行计划说明:
EXPLAIN语句提供有关MySQL如何执行语句的信息。EXPLAIN适用于SELECT、DELETE、INSERT、REPLACE和UPDATE语句。
EXPLAIN为SELECT语句中使用的每个表返回一行信息。它按照MySQL在处理语句时读取表的顺序列出输出中的表。MySQL使用嵌套循环连接方法解析所有连接。这意味着MySQL从第一个表中读取一行,然后在第二个表、第三个表中找到匹配行,依此类推。处理完所有表后,MySQL输出所选列并回溯表列表,直到找到一个匹配行更多的表。从该表中读取下一行,并继续处理下一个表。
首先看一下执行计划的的执行命令(本文mysql环境为5.7)。
explain select 语句
示例查询部门信息的执行计划
每个执行计划包含10个列信息。分别说明一下列信息
1.id
2.select_type
3.table
4.type
5.possible_keys
6.key
7.key_len
8.ref
9.rows
10.extra
select_type表示查询类型,常见的有以下几种:
simple:最简单的查询,只有select from 表,无其他查询。
primary :最简单查询包含子查询,最外层的为primary查询。比如说:select * from (select * from t2) t1
,其中最外层的是primary.
derived:在from 后面的子查询,比如说:select * from (select * from t2) t1
.其中t2表derived.
subquery:在select 或是where后面的查询为子查询,比如说:
select * from t1 where t1.id=(select * from t2)
.其中select * from t2
为subquery.
dependent_subquery:在select 或是where后面的子查询,并且子查询返回多个值的情况.比如说:
select * from t1 where t1.id in (select * from t2)
.其中select * from t2
为dependent_subquery.
union: 第二个select在union 之后,比如说:
select * from t1
union all
select * from t2
其中t2为union查询.
union result:union all联查的类型为union result。比如说:
select * from t1
union all
select * from t2
其中所有的查询为union result。
ref:对于前一个表中的每一行组合,将从此表中读取具有匹配索引值的所有行.出现场景:
where条件中有=,查询字段为非唯一索引的单表查询或是多表查询.示例(wy_client_user中mobile为普通索引,wy_client_user_summary通过mobile与wy_client_user进行关联):
range:部分索引扫描。当where条件后面查询字段为索引且使用(<>、>、>=、<、<、<=、<=、<,<、<=)中的任何运算符或是将键列与常量进行比较,或是使用between and和in时连接类型都会是range。示例(wy_client_user中id为主键索引,login为唯一索引):
index:全表索引扫描,执行效率比all要高一些,因为索引数量要比数据库中所有数据记录要少一些.一般出现的情况是查询字段为索引字段,没有where条件语句,示例:
all:全表查询,执行效率最低,应当避免.
type常见类型总结汇总:
key表示查询语句中实际用到的索引名称.
key_len表示查询语句中实际用到的索引名称的长度.
ref表示哪个字段或者常量与key一起被使用.如果是使用的常量等值查询,这里会显示const;如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段;如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func。
rows表示每个查询语句中查询的行数.大致估算此处查询需要读取的行数,不是精确值。