以下文章来源于南山的架构笔记 ,作者南山
搞清楚了MySQL索引的原理之后,就需要学习查询语句的执行计划和SQL调优,这块可能是MySQL实践中对开发人员为常见的一个技能了。
每次我们提交一个SQL查询语句给MySQL,他内核里的查询优化器,都会针对这个SQL语句的语义去生成一个执行计划,这个执行计划就代表了,他会怎么查各个表,用哪些索引,如何做排序和分组,看懂这个执行计划,你可能就会写出高性能的SQL语句了。
MySQL提供explain/desc命令输出执行计划,如explain select * from user;
一般,如果是一个简单的单表查询,可能执行计划就输出一条数据,如果你的SQL语句特别复杂,执行计划就会输出多条数据,因为一个复杂的SQL语句的执行会拆分为多个步骤,比如先访问表A,接着搞一个排序,然后来一个分组聚合,再访问表B,接着搞一个连接。
接下来,我们就先来研究一下这个执行计划里比较重要的字段都是什么意思。
(1)id
这个id呢,就是说每个SELECT都会对应一个id,其实说白了,就是一个复杂的SQL里可能会有很多个SELECT,也可能会包含多条执行计划,每一条执行计划都会有一个的id,这个没啥好说的。
(2)select_type
select_type说的就是这一条执行计划对应的查询是个什么查询类型
(3)table
table就是表名,意思是要查询哪个表。
(4)type
type就比较重要了,提供了判断查询是否高效的重要依据依据,一般有这几种情况:
const
ref
range
index
ref_or_null
all
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 6603| 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
|1| SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 1850 | 100.00 | NULL |
| 1| SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 6603 | 100.00 | Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
EXPLAIN SELECT * FROM t1 WHERE x1 IN (SELECT x1 FROM t2) OR x3 = 'xxxx';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
|1 | PRIMARY | t1 | NULL | ALL | index_x3 | NULL | NULL | NULL | 3457 | 100.00 | Using where |
| 2 | SUBQUERY | t2 | NULL | index | index_x1 | index_x1 | 507 | NULL | 4687 | 100.00 | Using index |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+