日常开发中,几乎都免不了和数据库打交道,说到数据库,我们也需要联想这几个问题:我们写的SQL性能怎么样?有没有优化的空间?如何优化?下面我们来介绍关于SQL性能的命令EXPLAIN
什么是EXPLAIN命令?
EXPLAIN
是 MySQL 中一个非常有用的命令,用于查看查询的执行计划。通过 EXPLAIN
,可以知道查询是如何被优化器执行的,了解 MySQL 如何选择索引、如何关联表等,从而帮助我们优化 SQL 查询。
执行 EXPLAIN
命令的方式:
EXPLAIN SELECT * FROM your_table WHERE your_conditions;
EXPLAIN详解
EXPLAIN
输出的每一行代表查询中的一步操作,而每一列提供了与查询计划相关的特定信息。主要列的含义如下:
1. id
- 含义:查询的步骤编号。
- 描述:
-
id
值相同的行,表示这些步骤可以并行执行。id
值不同的行,id
值越大,表示优先执行, 例如子查询,一般id值会比较大。
2. select_type
- 含义:表示查询的类型。
- 常见类型:
-
SIMPLE
:简单查询,不包含子查询或联合查询。PRIMARY
:查询中的主查询。SUBQUERY
:子查询中的第一层查询。DERIVED
:派生表(子查询的结果会作为临时表来使用)。UNION
:联合查询中的第二个或后续的 SELECT。UNION RESULT
:联合查询中的结果集。
3. table
- 含义:查询涉及的表名或别名。
4. partitions
- 含义:展示查询使用了哪些分区。通常用于分区表。
5. type
- 含义:访问类型,表示 MySQL 在查询时使用的访问方式。访问类型从好到差的排序如下:
-
system
:表中只有一行(系统表),这是特殊情况。const
:表只有一个匹配行,用于主键或唯一索引查询。eq_ref
:对于每个来自前一表的行,结合索引查询最多返回一行,通常是主键或唯一索引。ref
:非唯一索引扫描,返回匹配的所有行。range
:检索指定范围内的行,一般当使用IN
,BETWEEN
,<
,>
这种范围查询,基本回事这个类型。index
:全表扫描,但扫描的是索引树而不是数据行。ALL
:全表扫描。
6. possible_keys
- 含义:查询可能使用的索引。显示哪些索引能用于查询中的条件。
7. key
- 含义:MySQL 实际使用的索引。
8. key_len
- 含义:索引的长度。表示 MySQL 使用索引的字节数,越短表示索引利用率越高。
9. ref
- 含义:哪些列或常量被用于和
key
指定的索引进行比较。
10. rows
- 含义:MySQL 估计要读取的行数。基于统计信息,并非精确值。
11. filtered
- 含义:表示查询条件过滤后返回的行比例。数值为百分比。
12. Extra
- 含义:额外信息,描述查询的细节。
- 常见值:
-
Using index
:查询只使用索引,优化的表现,避免了访问数据行。Using where
:使用了WHERE
过滤条件。Using temporary
:MySQL 使用了临时表。Using filesort
:MySQL 需要对结果排序,可能是非索引排序,这是性能瓶颈之一。
示例
EXPLAIN SELECT * FROM employees WHERE salary > 5000;
可能的结果:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | employees | range | salary_idx | salary_idx | 4 | NULL | 1000 | 50.00 | Using where |
常见优化建议
- 避免
ALL
类型的查询:尽量避免全表扫描,确保使用了索引。 - 确保
Extra
中不出现Using filesort
和Using temporary
:它们表明查询效率不高,应该通过索引优化或调整查询来避免。 - 选择合适的索引:检查
possible_keys
和key
,确保查询使用了适当的索引。
我认为能最低的级别也需要达到type=range
, 如果是range
后面的,则代表这个SQL性能很差了,建议优化!