主要有这9个变量。
1. Select_scan
2. Select_range
3. Select_full_join
4. Select_range_check
5. Select_full_range_join
6. Sort_scan
7. Sort_range
8. Sort_merge_passes
9. Sort_rows
其中 Select_scan 和 Select_range 包括了单表查询和多表联接查询中的第一个表。Select_full_join, Select_range_check 和 Select_full_range_join 用于多表联接查询中的第二张及之后的表。Sort 的那几个变量则用于任何需要排序的查询。
Select_scan
代表了需要做全表扫描。在 explain 中 type 会显示为 ALL,原因是查询没有能用到索引。因为全表扫描一般比较慢,所以应该尽量避免。
Select_range
代表需要从硬盘读表在一段范围内的行。在 explain 中显示为 range,说明使用了索引查找记录在硬盘上的位置。
Select_full_join
和 Select_scan 差不多,区别是 Select_full_join 代表的是第二张及之后的表。explain 中的类型也是 ALL,原因是表联接所用的字段上没有索引。它对性能有更为严重的影响,绝对要避免,所以用于联接的字段上一般都要加索引。
Select_range_check
这个比 Select_full_join 要好一点,和 Select_range 差不多。区别是 MySQL 不能确定它是否能否使用一个范围来做联接。如果可以那么会使用范围,如果不行仍会使用全表扫描。在 explain 中 type 也会是 ALL,但 extra 中会有 Range checked for each record (index map: ) 的说明。不能肯定是否能用范围是因为联接是条件不确定。如:
SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 > tbl2.col1
如果 tbl2.col1 上有索引,那么可以做 Select_range_check,explain的结果如下
mysql> EXPLAIN SELECT * FROM tbl1, tbl2 WHERE tbl1.col1 > tbl2.col1;
+-------------+-------+------+---------------+------+---------+------+------+------------------------------------------------+
| select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+-------------+-------+------+---------------+------+---------+------+------+------------------------------------------------+
| SIMPLE | tbl1 | ALL | NULL | NULL | NULL | NULL | 27 | |
| SIMPLE | tbl2 | ALL | col1 | NULL | NULL | NULL | 18 | Range checked for each record (index map: 0x1) |
+-------------+-------+------+---------------+------+---------+------+------+------------------------------------------------+
如果链接 tbl2 的时候 MySQL 判断可以使用范围查找,它仍然会增加 Select_range_check 而不是 Select_range。
Select_full_range_join
和 Select_range_check 类似,不过 MySQL 可以肯定它能够使用范围查找。这时 explain 中的类型是 range。这是联接中最好的情况。
Sort_scan 和 Sort_range
查询做排序,不论是因为 order by 还是 group by(除了使用了 order by NULL 的 group by),主要都是下面的三步:
1. 通过 where 条件找到记录
2. 排序
3. 按排好的顺序读取记录
如果第二步不被跳过,那么第三步中就会有 Sort_scan 或 Sort_range。如果第一步是 Select_scan,那么第三步将是 Sort_scan,如果第一步是 Select_range,那么第三步会是 Sort_range。但 Sort_scan 和 Sort_range 其实没有功能上的区别,都是将需要的记录按顺序读出来,所以性能也是一样的。
Sort_merge_passes
Sort_merge_passes 包括两步。MySQL 首先会尝试在内存中做排序,使用的内存大小由系统变量 Sort_buffer_size 决定,如果它的大小不够把所有的记录都读到内存中,MySQL 就会把每次在内存中排序的结果存到临时文件中,等 MySQL 找到所有记录之后,再把临时文件中的记录做一次排序。这再次排序就会增加 Sort_merge_passes。实际上,MySQL 会用另一个临时文件来存再次排序的结果,所以通常会看到 Sort_merge_passes 增加的数值是建临时文件数的两倍。因为用到了临时文件,所以速度可能会比较慢,增加 Sort_buffer_size 会减少 Sort_merge_passes 和 创建临时文件的次数。但盲目的增加 Sort_buffer_size 并不一定能提高速度,见 How fast can you sort data with MySQL ?
Sort_row
这代表了在第二步中被排序的记录的总数。因为 Sort_range 和 Sort_scan 是一样的,所以这个值只是说明了有多少记录被排序,意思不大。