MySQL EXPLAIN
详解
EXPLAIN
是 MySQL 中用来分析 SQL 查询执行计划的命令,能够帮助开发者了解查询优化器如何执行查询,并识别潜在的性能瓶颈。通过 EXPLAIN
,我们可以获取查询的执行顺序、索引使用情况、表扫描方式等信息,从而优化查询性能。
EXPLAIN
可以用于 SELECT、DELETE、INSERT 和 UPDATE 语句,以查看其执行计划。
1. 基本语法
EXPLAIN [EXTENDED] SELECT * FROM your_table WHERE your_conditions;
EXPLAIN
:用于显示查询的执行计划。EXTENDED
(可选):显示更详细的执行计划,包括优化器的选择过程,特别是在子查询中。
示例:
EXPLAIN SELECT * FROM employees WHERE department_id = 10;
2. EXPLAIN
输出字段说明
执行 EXPLAIN
命令时,MySQL 会输出以下字段,这些字段提供了查询执行计划的详细信息:
字段名称 | 描述 |
---|---|
id | 查询的标识符。通常用于区分不同的查询,数字越小的查询先执行。如果有子查询,则子查询的 id 值会大于主查询的 id 。 |
select_type | 查询的类型。标明了查询的执行方式。常见值有: SIMPLE (简单查询) PRIMARY (主查询) UNION (联合查询) SUBQUERY (子查询) |
table | 当前查询涉及的表。显示当前处理的表名。 |
type | 连接类型,表示查询中从表中读取数据的方式,连接类型对查询性能有很大的影响。常见值有: ALL (全表扫描) index (索引扫描) range (范围扫描) ref (查找单一值) eq_ref (等值连接) const (常量值) NULL (没有访问数据) |
possible_keys | 查询可能使用的索引。MySQL 优化器认为可以用来加速查询的索引列表。 |
key | 实际使用的索引。如果查询没有使用索引,显示 NULL 。 |
key_len | 使用的索引的长度。表示 MySQL 实际用于检索的索引的字节数。 |
ref | 显示哪些列或常数与 key 列一起用于查找数据。通常是 const 或表中的列。 |
rows | 估算扫描的行数。MySQL 优化器基于索引和查询条件来预测需要扫描的行数。 |
Extra | 额外的信息,提供有关查询执行的其他细节。常见的值有: Using index (只使用索引,不需要访问表数据) Using where (在扫描过程中应用了 WHERE 子句) Using temporary (查询使用了临时表) Using filesort (查询需要进行文件排序) |
3. 示例分析
假设我们有如下的查询:
EXPLAIN SELECT * FROM employees WHERE department_id = 10;
假设输出:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | employees | ref | department_idx | department_idx | 4 | const | 100 | Using where |
字段解释:
- id:查询的 ID 是
1
,说明这是主查询(没有子查询)。 - select_type:查询类型是
SIMPLE
,表示这是一个简单的查询,没有子查询。 - table:当前查询操作的表是
employees
。 - type:查询类型是
ref
,表示它使用了一个索引来查找行(ref
类型通常用于非唯一索引)。 - possible_keys:可能使用的索引是
department_idx
,该索引可能被用于优化查询。 - key:实际使用的索引是
department_idx
,表明查询实际使用了索引来加速查找。 - key_len:使用的索引的长度为
4
字节,表明索引列的长度。 - ref:
const
,表示department_id
的值是常量(在WHERE
子句中)。 - rows:预计扫描的行数是
100
,表示 MySQL 预计扫描 100 行数据。 - Extra:
Using where
,表示在查询过程中应用了WHERE
子句。
4. 优化 EXPLAIN
输出
EXPLAIN
可以帮助识别查询的潜在问题,并进行优化:
4.1 全表扫描 (ALL
)
如果 type
显示为 ALL
,则表示查询正在执行全表扫描,这通常意味着没有使用索引,查询性能可能很差。
解决方案:
- 为查询的列创建合适的索引。
- 检查查询条件和索引是否匹配。
4.2 使用索引
如果查询没有使用任何索引,或者 key
显示为 NULL
,则表明查询没有利用索引,这可能导致查询效率低下。
解决方案:
- 确保查询中使用了正确的索引。
- 如果查询使用了不合适的索引,考虑优化索引或调整查询条件。
4.3 文件排序 (Using filesort
)
如果 Extra
列显示 Using filesort
,表示查询在排序时使用了外部排序(通常是磁盘上的临时文件),这通常会影响性能。
解决方案:
- 确保查询中的
ORDER BY
子句使用了索引。 - 尽量避免对大数据集进行排序操作。
4.4 临时表 (Using temporary
)
如果 Extra
列显示 Using temporary
,表示查询使用了临时表来处理中间结果,这通常意味着查询涉及到复杂的 JOIN 或子查询,可能会影响性能。
解决方案:
- 优化查询,减少临时表的使用。
- 考虑拆分查询,减少临时表的需求。
5. EXPLAIN
的扩展使用
5.1 EXPLAIN EXTENDED
EXPLAIN EXTENDED
会提供更多的查询优化信息,尤其在子查询和优化器选择方面非常有用。
EXPLAIN EXTENDED SELECT * FROM employees WHERE department_id = 10;
5.2 EXPLAIN
与 ANALYZE
EXPLAIN ANALYZE
在 MySQL 8.0.18 及以上版本中可用。它不仅提供执行计划,还包括实际的执行时间和其他运行时数据。
EXPLAIN ANALYZE SELECT * FROM employees WHERE department_id = 10;
这对于调优和评估查询实际性能非常有帮助。
6. 总结
EXPLAIN
是分析 SQL 查询性能的强大工具,帮助开发者理解查询如何执行并优化查询。通过查看 EXPLAIN
的输出,开发者可以:
- 识别全表扫描或缺乏索引的问题。
- 发现性能瓶颈,如文件排序和临时表的使用。
- 进一步优化查询,提高数据库的响应速度和效率。
发表回复