EXPLAIN命令是MySQL中用于分析SQL查询语句执行计划的重要工具。通过EXPLAIN,可以深入了解MySQL是如何处理SQL语句的,包括表的读取顺序、数据读取操作类型、索引的使用情况等信息。这些信息对于优化SQL语句、提升数据库性能至关重要。
使用示例
假设employees
表有以下结构:
employee_id
(主键)first_name
last_name
department_id
(有索引)hire_date
- …(其他列)
并且假设department_id
和hire_date
上都有单独的索引,或者有一个复合索引包含这两个列。
执行以下查询:
EXPLAIN SELECT * FROM employees WHERE department_id = 10 AND hire_date BETWEEN '2020-01-01' AND '2020-12-31';
可能会得到下面的结果:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | employees | range | dept_index,hire_date_index | dept_index | 4 | NULL | 100 | Using where |
现在,让我们解释每个字段:
- id:
1
表示这是查询中的第一个(也是唯一一个)SELECT语句。 - select_type:
SIMPLE
表示这是一个简单的SELECT查询,没有子查询或UNION。 - table:
employees
表示查询涉及的是employees
表。 - type:
range
表示MySQL使用了一个索引来检索给定范围内的行。在这个例子中,可能是因为department_id
有索引,并且hire_date
也有索引,但MySQL选择使用department_id
的索引先过滤出部门ID为10的行,然后再在这些行中检查hire_date
是否满足条件。实际使用的索引取决于索引的选择和MySQL的优化决策。 - possible_keys:
dept_index,hire_date_index
表示MySQL认为可能用于查询的索引。这些索引可能是单独针对department_id
和hire_date
的,或者是一个包含这两个列的复合索引。 - key:
dept_index
表示MySQL实际决定使用的索引。在这个例子中,假设MySQL选择了使用department_id
的索引。 - key_len:
4
表示MySQL在索引中使用了4个字节。这通常与索引字段的数据类型有关。例如,如果department_id
是一个INT
类型,那么它通常是4个字节。 - ref:
NULL
表示没有使用列的引用或比较来查找索引列上的值。在range
类型的查询中,这通常是正常的,因为查询是在一个范围内查找值,而不是查找特定的值。 - rows:
100
表示MySQL估计为了找到所需的记录需要检查大约100行。这是一个估算值,实际检查的行数可能会更多或更少。 - Extra:
Using where
表示在检索出行后,MySQL还需要应用一个WHERE条件来过滤结果。在这个例子中,即使使用了department_id
的索引,MySQL仍然需要在检索出的行中检查hire_date
是否满足条件。
下面是对返回结果中各字段的详细解释:
返回结果字段解释
-
id:
- 技术含义:这是SELECT查询的序列号,用于表示查询中执行select子句或操作表的顺序。
- 示例解释:如果查询中只有一个SELECT语句,那么id通常为1。如果存在子查询或联合查询,MySQL会为每个SELECT语句分配一个唯一的id。在嵌套查询中,id值越大的语句越先执行。
-
select_type:
- 技术含义:表示查询的类型,用于区分简单查询、联合查询、子查询等复杂查询。
- 示例解释:对于上述查询,如果它是一个简单的SELECT查询(不包含子查询或UNION),那么select_type通常为SIMPLE。如果存在子查询,最外层的查询会被标记为PRIMARY,子查询则可能被标记为SUBQUERY或DERIVED。
-
table:
- 技术含义:显示这一行的数据是关于哪张表的。
- 示例解释:在上述查询中,table字段的值应该是employees,表示查询涉及的是employees表。
-
type:
- 技术含义:这是非常重要的一个字段,表示MySQL如何查找表中的数据行。其值从好到差依次为:system > const > eq_ref > ref > range > index > ALL。
- 示例解释:如果查询使用了索引并且索引选择得很好,type字段的值可能是ref或range。如果查询是全表扫描,那么type的值就是ALL,这通常意味着查询性能较差,需要考虑优化。
-
possible_keys:
- 技术含义:显示MySQL认为可能用于查询的索引。
- 示例解释:对于上述查询,如果employees表上有针对department_id和hire_date的索引,那么这些索引可能会被列出在possible_keys字段中。
-
key:
- 技术含义:表示MySQL实际决定使用的索引。
- 示例解释:如果查询中实际使用了某个索引,那么该索引的名称会出现在key字段中。如果查询没有使用索引,那么key字段的值为NULL。
-
key_len:
- 技术含义:表示MySQL在索引中使用的字节数。
- 示例解释:key_len字段的值可以帮助我们了解索引使用的长度。如果索引是多列的,那么查询不一定能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去。
-
ref:
- 技术含义:显示哪些列或常量被用于查找索引列上的值。
- 示例解释:如果查询中使用了某个列的值来查找索引列上的值,那么该列的名称会出现在ref字段中。
-
rows:
- 技术含义:表示MySQL估计查询需要检查的行数。
- 示例解释:rows字段的值是一个估算值,表示MySQL认为为了找到所需的记录需要检查的行数。这个值越小越好,表示查询效率越高。
-
Extra:
- 技术含义:包含MySQL解决查询的详细信息,如是否使用了文件排序、临时表等。
- 示例解释:如果查询中使用了文件排序(Using filesort),那么Extra字段会包含这个信息。文件排序通常意味着查询性能较差,因为MySQL无法利用索引完成排序操作。另外,如果查询使用了临时表(Using temporary),也说明查询性能可能不佳。
结语
- 表的读取顺序:通过id字段可以了解查询中各个表的读取顺序。
- 数据读取操作类型:type字段反映了MySQL如何查找表中的数据行,是评估查询性能的关键指标。
- 索引的使用情况:possible_keys和key字段显示了MySQL可能使用和实际使用的索引,对于优化查询性能至关重要。
- 查询效率:rows字段的估算值可以帮助我们了解查询需要检查的行数,从而评估查询效率。
- 额外信息:Extra字段提供了查询过程中MySQL使用的额外信息,如是否使用了文件排序、临时表等,对于进一步优化查询性能提供了线索。
通过EXPLAIN命令,我们可以深入了解MySQL如何执行SQL查询语句,从而找出性能瓶颈并进行针对性的优化。无论是选择更好的索引、优化查询逻辑还是调整数据库结构,EXPLAIN都是不可或缺的工具。