从小有一片土地叫做数据库,数据库上分成几个国家:Oracle、Sybase、DB2、SQL server、Access、MySQL、BD2等等。Oracle是其中的大霸主,MySQL近年来迅速扩张,逐步在吞没其他国家的土地。
今天我们来说说MySQL中的医疗部门--EXPLAIN。
explain主要提供select语句的执行计划信息。select语句是叫做sql生物的其中一种,有了explain的协助可以更加方便地为select语句体检,根据情况判断出该select语句的身体健康状态。
一个优秀的select语句需要经常运动并且定期检查,explain可以开启慢sql检查,对进进出出需要执行任务的sql语句进行安检。
一份合格的体检报告一般包含以下几个内容:
EXPLAIN Output Columns
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 |
一般来体检的语句分为两种:
① select语句自身觉得可能生病了,然后就会主动联系explain,把自己的身体情况详细介绍清楚,比如select * from aa where id > 5;;
② 另外一种就是被安检出来,你造一般情节,这类的sql语句都会东躲西藏,就算被抓到还是会吞吞吐吐,比如
select * from bb where id > 'xxx'; 完全就是负隅顽抗不想告诉你xxx是什么。= =
检查步骤:
1. 通过各种方式得到一个可执行的select语句。
在explain部门进行检查之前我们必须要保证这个select语句是可执行的,既然它不想告诉我们,我们只能自己构造出一个合适的可执行的sql语句。
2. 有些select语句过于臃肿,每一个部分都被仔细检查了一遍,得到的报告一堆又一堆,年轻人容易两眼蚊香状,可以拆分,部分检查判断部分健康状况。
在物欲横生的时代,臃肿并不是罕见的情况,被抓住的往往是各种联表查询,一层套一层的select from。
3. 关注重点指标:type、key、rows、extra
- type值,由好到差的排序如下所示:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
- key:引用的索引值,可以配合possible_keys一起查看,当然possible_keys只是做参考,有时候推荐的也不一定是适用的
- rows:
The rows column indicates the number of rows MySQL believes it must examine to execute the query.
这个rows就是mysql认为必须要逐行去检查和判断的记录的条数。
举个例子来说,假如有一个语句 select * from t where column_a = 1 and column_b = 2;
全表假设有100条记录,column_a字段有索引(非联合索引),column_b没有索引。
column_a = 1 的记录有20条, column_a = 1 and column_b = 2 的记录有5条。那么最终查询结果应该显示5条记录。 explain结果中的rows应该是20,因为这20条记录mysql引擎必须逐行检查是否满足where条件。
-
extra
MySQL must do an extra pass to find out how to retrieve the rows in sorted order. The sort is done by going through all rows according to the join type and storing the sort key and pointer to the row for all rows that match the WHERE clause.
MYSQL需要一次额外的传递找到如何按照排序顺序检索行。根据连接的类型查询所有行,为所有匹配where语句的行存储排序关键字和行指针来完成排序。
有order by语句,但是索引加得不得当 → 对sql语句和索引进行优化,但并不是说出现了using filesort就需要优化,主要判断标准在于是否影响到性能。
题外话:
联合索引:
key ('A1','A2','A3','A4'),排序的思路一般是,先按照A1来排序,A1相同,然后按照A2排序,以此类推,这样对于(A1), (A1, A2), (A1, A2, A3)的索引都是有效的,但是对于(A2, A3)这样的索引就无效了。
② Using where:表示优化器需要通过索引回表查询数据;
③ Using index:表示直接访问索引就足够获取到所需要的数据,不需要通过索引回表;
④ Using index condition:在5.6版本后加入的新特性(Index Condition Pushdown);
Q1. What's the difference between "Using index condition" and "Using where;Using index" in the EXPLAIN?
Q2. Which is better?
Using index condition : where condition contains indexed and non-indexed column and the optimizer will first resolve the indexed column and will look for the rows in the table for the other condition (index push down)
Using where; Using index : 'Using index' meaning not doing the scan of entire table. 'Using where' may still do the table scan on non-indexed column but it will use if there is any indexed column in the where condition first more like using index condition
Which is better? 'Using where; Using index' would be better then 'Using index condition' if query has index all covering.
Q3. What's the difference between "Using index" and "Using where;Using index" in the EXPLAIN?
这个问题相对简单一点,可以参考:http://stackoverflow.com/questions/25672552/whats-the-difference-between-using-index-and-using-where-using-index-in-the
Q4. 为什么EXPLAIN SELECT customer_id FROM rental WHERE customer_id>=300;会使用索引,而 EXPLAIN SELECT * FROM rental WHERE customer_id>=300; 则不会使用索引呢?
优化器会在索引存在的情况下,通过符合 RANGE 范围的条数和总数的比例来选择是使用索引还是进行全表遍历。
当需要读取的数据超过一个临界值时,优化器会放弃从索引中读取而改为进行全表扫描,这是为了避免过多的 random disk。
4. 根据体检报告对sql语句进行合适的建议,优化后再次体检,共同奔向社会主义和谐社会。
注意:explain只能做建议,不能完全依靠。
好了,我编不下去了。
参考资料如下所示:
http://dev.mysql.com/doc/refman/5.7/en/explain-output.html
除了该链接外还参考了http://stackoverflow.com/questions上的一些问题以及答案,比较浅薄地介绍一下,欢迎指摘。