一、了解Explain
explain的含义是执行计划,使用explain关键字可以模拟优化器执行sql查询语句,用于分析查询语句或表结构的性能瓶颈。显示了mysql如何使用索引来处理select语句以及连接表,从而知道MySQL是如何处理sql语句,可以帮助选择更好的索引和写出更优化的查询语句。
使用了explain关键子可以直到下面几项内容:
1、表的读取顺序。(对应id)
2、数据读取操作的操作类型。(对应select_type)
3、哪些索引可以使用。(对应possible_keys)
4、哪些索引被实际使用。(对应key)
5、表直接的引用。(对应ref)
6、每张表有多少行被优化器查询。(对应rows)
二、使用Explain
只需要在sql前面加上explain关键字就可以了。
explain select * FROM a where a_id = 1 and src_text="XXX";
执行后显示如下结果:
id:SELECT识别符。
这是SELECT的查询序列号,select子句或表执行顺序,id相同,从上到下执行,id不同,id值越大,执行优先级越高。
select_type:数据读取操作的操作类型。
select_type的值有
- SIMPLE
简单SELECT(不使用UNION或子查询)
- PRIMARY
最外面的SELECT
- UNION
UNION中的第二个或后面的SELECT语句,当通过UNION来连接多个查询结果时,第二个之后的select其select_type为UNION。
explain select * from a where a_id=1 union select * from a where a_id=2;
- DEPENDENT UNION
UNION中的第二个或后面的SELECT语句,取决于外面的查询。当union作为子查询时,其中第二个union的select_type就是DEPENDENT UNION。
explain select * from a where a_id in
(select a_id from a where a_id=1 union select a_id from a where a_id=2);
- UNION RESULT
UNION 的结果
- SUBQUERY
子查询中的第一个SELECT
- DEPENDENT SUBQUERY
当union作为子查询时,其中第二个union的select_type就是DEPENDENT UNION。子查询中的第一个SELECT,取决于外面的查询。
explain select * from a where a_id in
(select a_id from a where a_id=100 union select a_id from a where a_id=200);
- DERIVED
导出表的SELECT(FROM子句的子查询)
table:显示这一行的数据是关于哪张表的
type:这是重要的列,显示连接使用了何种类型。
type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref。
type列返回值的含义:
- system
表仅有一行(=系统表)。这是const联接类型的一个特例。
- const
表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
- eq_ref
对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。
- ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。
- ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。
- index_merge
该联接类型表示使用了索引合并优化方法。
- unique_subquery
该类型替换了下面形式的IN子查询的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
- index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
- range
只检索给定范围的行,使用一个索引来选择行。
- index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
- ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。
possible_keys:显示可能应用在这张表中的索引。
如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key: 实际使用的索引列。
如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len:使用的索引的长度。
在不损失精确性的情况下,长度越短越好
ref:显示索引的哪一列被使用了。
如果可能的话,是一个常数
rows:MYSQL认为必须检查的用来返回请求数据的行数。
filtered:显示了通过条件过滤出的行数的百分比估计值。
Extra:关于MYSQL如何解析查询的额外信息。
Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢。
extra列返回值的含义:
- Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了。
- Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了。
- Range checked for each Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一。
- Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。
- Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候。
- Using temporary
看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上。
- Where used
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)。
- Using where
WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。
- Using sort_union(...), Using union(...), Using intersect(...)
这些函数说明如何为index_merge联接类型合并索引扫描。
- Using index for group-by
类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。
三、总结
本篇文章做了简单的总结,重在了解explain关键字,过程中参考了两片写的不错的文章。