MySQL - 查询优化指南之『EXPLAIN 命令』详解

        EXPLAIN 是 MySQL 中用于分析 SQL 查询执行计划的关键工具,它能帮助开发者理解查询的执行方式并找出性能瓶颈。下面我将详细介绍 EXPLAIN 的使用方法和输出字段的含义,并通过实际示例说明如何优化查询。

 1.EXPLAIN 基础用法

EXPLAIN SELECT * FROM users WHERE id = 1;

 2.EXPLAIN 输出字段详解

EXPLAIN结果示例:

+----+-------------+-------+-------+-----------------+-----------------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys   | key             | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+-----------------+-----------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | users | range | idx_age_username| idx_age_username| 4       | NULL | 500  | Using where; Using index |
+----+-------------+-------+-------+-----------------+-----------------+---------+------+------+--------------------------+

1. id (查询标识符)

  • 表示 SELECT 查询的序列号
  • 相同 id 表示同一查询的不同部分
  • 不同 id 按从大到小执行,相同 id 按从上到下执行

2. select_type (查询类型)

类型描述
SIMPLE简单查询(不包含子查询或UNION)
PRIMARY最外层查询
SUBQUERY子查询中的第一个SELECT
DERIVED派生表(FROM子句中的子查询)
UNIONUNION中的第二个或后面的SELECT
UNION RESULTUNION的结果

 3. table (访问的表)

  • 显示查询涉及的表名
  • 如果是派生表,显示为 `<derivedN>`
  • 如果是联合结果,显示为 `<unionM,N>`

4. type (访问类型)  - 『最重要字段』

表示 MySQL 如何查找表中的行,从最优到最差排序:

类型描述优化建议
system表只有一行记录无需优化
const通过主键或唯一索引查找单行最佳情况
eq_ref多表关联时使用主键或唯一索引理想连接
ref使用非唯一索引查找常见高效类型
range索引范围扫描可接受
index全索引扫描考虑优化
ALL全表扫描需要优化

5. possible_keys (可能使用的索引)

  • 查询可能使用的索引列表
  • 如果为 NULL,表示没有可用的索引

6. key (实际使用的索引)

  • 查询实际使用的索引
  • 如果为 NULL,表示没有使用索引

7. key_len (使用的索引长度)

  • 表示索引中使用的字节数
  • 可以判断是否使用了索引的全部部分

 8. ref (索引比较的列)

  • 显示索引与哪些列或常量进行比较

 9. rows (预估需要检查的行数)

  • MySQL 估计要检查的行数
  • - 值越小越好

10. filtered (过滤百分比)

  • 表示存储引擎返回的数据在server层过滤后剩余的比例
  • 100表示没有过滤

11. Extra (额外信息) - 『重要优化提示』

包含 MySQL 解决查询的额外信息:

信息含义优化建议
Using index使用覆盖索引良好
Using where在存储引擎检索后过滤可能需要索引
Using temporary使用临时表需要优化
Using filesort使用文件排序需要优化
Using join buffer使用连接缓冲可调整join_buffer_size

3.实际优化案例分析

案例1:全表扫描问题

原始查询:

EXPLAIN SELECT * FROM orders WHERE customer_id = 100;

输出:

+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | orders | ALL  | NULL          | NULL | NULL    | NULL | 100000 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+

问题分析:

  • type: ALL 表示全表扫描
  • key: NULL 表示没有使用索引
  • rows: 100000 需要扫描所有行

优化方案:

ALTER TABLE orders ADD INDEX idx_customer_id (customer_id);

优化后 EXPLAIN:

+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+-------+
| id | select_type | table  | type | possible_keys   | key             | key_len | ref   | rows | Extra |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+-------+
|  1 | SIMPLE      | orders | ref  | idx_customer_id | idx_customer_id | 5       | const | 10   |       |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+-------+

案例2:文件排序问题

原始查询:

EXPLAIN SELECT * FROM products ORDER BY price DESC;

输出:

+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | products | ALL  | NULL          | NULL | NULL    | NULL | 5000 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+

问题分析:

  • -Extra: Using filesort 表示需要额外排序
  • - 没有使用索引进行排序

优化方案:

ALTER TABLE products ADD INDEX idx_price (price);

优化后 EXPLAIN:

+----+-------------+----------+-------+---------------+-----------+---------+------+------+-------+
| id | select_type | table    | type  | possible_keys | key       | key_len | ref  | rows | Extra |
+----+-------------+----------+-------+---------------+-----------+---------+------+------+-------+
|  1 | SIMPLE      | products | index | NULL          | idx_price | 4       | NULL | 5000 |       |
+----+-------------+----------+-------+---------------+-----------+---------+------+------+-------+

 4.高级优化技巧

1. 复合索引顺序:将选择性高的列放在前面
2. 避免索引失效:不要在索引列上使用函数或计算
3. 使用覆盖索引:只查询索引包含的列
4. 优化JOIN操作:确保JOIN字段有索引
5. 避免SELECT  * :只查询需要的列
6. 合理使用子查询:有时JOIN比子查询更高效

通过系统分析 EXPLAIN 输出,结合这些优化技巧,可以显著提升 MySQL 查询性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值