我们所写的SQL查询性能要考虑到真实的业务场景,有的SQL在实际生产环境下查询变慢,就要去分析优化他,首选就是采用explain这个mysql自带工具,它非常方便只需要在sql前加上explain关键字运行即可。运行会发现它是一个列表,每一列所代表的意思也有所不同。如下图所示:
explain中主要的列
id列
id不一定唯一,代表着执行顺序。id越大优先级越高,相等的话谁靠前谁先执行。
select_type列
select_type表示对应行是简单还是复杂的查询
- simple: 简单查询。查询不包含子查询和union
- primary: 复杂查询中最外层的select
- subquery: 包含在select的子查询(不在from子句中)
- derived: 包含在from子句中的子查询。Mysql会将结果存放一个临时表中,也称为派生表。
table列
对应一行正在访问哪个表
type列
这一列表示关联类型或访问类型,即Mysql决定如何查找表中的行,查找数据行记录的大概范围。
依此从最优到最差依此为:system>const>eq_ref>ref>range>index>all
一般情况下,得保证查询达到range级别,最好是ref。
- null: mysql能够在优化阶段分解查询语句,在执行阶段不用在访问表和索引
- const/system: mysql能对其优化并将其转为一个常量,用于主键和唯一索引的所有列与常数比较时,所以表中最多有一个匹配行,读取1次,速度比较快。system是const的特例表里只有一条匹配时为system。
- eq_ref: 主键或唯一索引的所有部分被连接使用,最多只会返回一条符合条件的记录。
- ref: 相比eq_ref,不使用唯一索引,而是使用普通索引或唯一索引的部分前缀,索引要和某个值比较,可能会找到多行。
- range: 范围查找,使用一个索引来检索给定范围的行。
- index: 扫描全索引就能拿到结果,一般是扫描某个二级索引,一般为覆盖索引。(原因是当mysql确定我们返回的字段在二级索引里能直接拿到,不用回表,会先使用二级索引,二级索引比主键小。没有符合的二级索引才走聚簇索引也就是全表扫描。)
- all: 全表扫描,扫描聚簇索引的所有叶子节点。这种需要增加索引来优化。
possible_keys列
可能使用哪些索引来查找
key列
实际走的索引
key_len列
在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。
ref列
这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有const(常量),字段名(例:film.id)
rows列
这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。
extra列
这一列展示的是额外信息。常见的重要值如下(以下只供参考):
- Using index: 使用覆盖索引
- Using where: 需要优化,使用where语句来处理结果,并且查询的列未被索引覆盖(没有走索引)
- Using index condition: 查询的列不完全被索引覆盖,where条件中是一个前导列的范围
- Using temporart: 需要优化,需要创建一个临时表来处理查询。比如distinct一个没有索引的列。(如果distinct是有索引的列(显示为Using index),就不需要临时表了,查询对应列维护的索引树即可,它是有序的)
- Using filesort: 需要优化,将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。(如果order by一个有索引的列,显示为Using index)