MySQL中 EXPLAIN 的使用介绍

Day08-11. MySQL-索引-结构_哔哩哔哩_bilibili

使用 EXPLAIN

在查询语句前加上 EXPLAIN 关键字:

EXPLAIN SELECT * FROM orders WHERE customer_id = 123 AND order_date > '2023-01-01';

执行上述 EXPLAIN 语句,查看输出结果。MySQL 会返回一个包含查询执行计划的表格(如下)。

具体解释:

EXPLAIN 输出表格包含多个列,每列提供不同的查询计划信息。常见列包括:

1、id:查询的标识符,表示查询的执行顺序。

2、select_type:查询类型,如 SIMPLE(简单查询),PRIMARY(主查询),UNION(联合查询的一部分),SUBQUERY(子查询)。

3、table:查询涉及的表。

4、type:连接类型,表示MySQL如何查找行。常见类型按效率从高到低排列为:

  • system:表只有一行(常见于系统表)。

  • const:表最多有一个匹配行(索引为主键或唯一索引)。

  • eq_ref:对于每个来自前一个表的行,表中最多有一个匹配行。

  • ref:对于每个来自前一个表的行,表中可能有多个匹配行。

  • range:使用索引查找给定范围的行。

  • index:全表扫描索引。

  • ALL:全表扫描。

5、possible_keys:查询中可能使用的索引。

6、key:实际使用的索引。

7、key_len:使用的索引键长度。

8、ref:使用的列或常量,与索引比较。

9、rows:MySQL 估计的要读取的行数。

10、filtered:经过表条件过滤后的行百分比。

11、Extra:额外的信息,如 Using index(覆盖索引),Using where(使用 WHERE 子句过滤),Using filesort(文件排序),Using temporary(使用临时表)。

优化查询路径

根据 EXPLAIN 输出,采取以下措施优化查询路径:

确保使用索引

如果 type 列显示为 ALL 或 index,说明表进行了全表扫描。可以通过创建适当的索引来优化查询。例如:

CREATE INDEX idx_customer_date ON orders (customer_id, order_date);

优化查询条件

避免在索引列上使用函数或进行计算。改写查询条件以利用索引。例如:

-- 避免SELECT * FROM orders WHERE YEAR(order_date) = 2023;

-- 改为SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';

使用覆盖索引

如果查询只涉及索引中的列,可以避免回表,提高性能。例如:

CREATE INDEX idx_covering ON orders (customer_id, order_date, order_id);
-- 查询只涉及索引中的列SELECT customer_id, order_date, order_id FROM orders WHERE customer_id = 123;

分解复杂查询

将复杂查询分解为多个简单查询,可以提高性能。例如:

-- 复杂查询SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.name = 'John Doe';
-- 分解为两个简单查询SELECT id FROM customers WHERE name = 'John Doe';-- 假设查询结果为 123SELECT * FROM orders WHERE customer_id = 123;

实际示例

假设有一个 employees 表和一个 departments 表:

CREATE TABLE employees (    id INT AUTO_INCREMENT PRIMARY KEY,    first_name VARCHAR(50),    last_name VARCHAR(50),    department_id INT,    hire_date DATE,    INDEX (department_id),    INDEX (hire_date));
CREATE TABLE departments (    id INT AUTO_INCREMENT PRIMARY KEY,    name VARCHAR(50));

查询所有在某个日期后加入某部门的员工:

EXPLAINSELECT e.id, e.first_name, e.last_nameFROM employees eJOIN departments d ON e.department_id = d.idWHERE d.name = 'Sales' AND e.hire_date > '2023-01-01';

示例 EXPLAIN 输出:

+----+-------------+-------+--------+---------------+---------+---------+-------------------+------+--------------------------+| id | select_type | table | type   | possible_keys | key     | key_len | ref               | rows | Extra                    |+----+-------------+-------+--------+---------------+---------+---------+-------------------+------+--------------------------+|  1 | SIMPLE      | d     | const  | PRIMARY       | PRIMARY | 4       | const             |    1 |                          ||  1 | SIMPLE      | e     | ref    | department_id | department_id | 4 | const             |   10 | Using where              |+----+-------------+-------+--------+---------------+---------+---------+-------------------+------+--------------------------+

从 EXPLAIN 输出可以看出:

  • d 表使用了 PRIMARY 索引,类型为 const,表示是一个常量查找。

  • e 表使用了 department_id 索引,类型为 ref,表示引用查找。

进一步优化:

  • 如果查询频繁,可以为 departments.name 创建索引。

  • 确保 hire_date 上有索引。

优化后的索引创建:

CREATE INDEX idx_department_name ON departments (name);

再次执行 EXPLAIN:

EXPLAINSELECT e.id, e.first_name, e.last_nameFROM employees eJOIN departments d ON e.department_id = d.idWHERE d.name = 'Sales' AND e.hire_date > '2023-01-01';

优化后的输出可能显示更好的执行计划,减少查询时间。

相关推荐
The_Ticker16 分钟前
CFD平台如何接入实时行情源
java·大数据·数据库·人工智能·算法·区块链·软件工程
Elastic 中国社区官方博客22 分钟前
Elasticsearch 开放推理 API 增加了对 IBM watsonx.ai Slate 嵌入模型的支持
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
企鹅侠客26 分钟前
ETCD调优
数据库·etcd
Json_1817901448033 分钟前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
煎饼小狗44 分钟前
Redis五大基本类型——Zset有序集合命令详解(命令用法详解+思维导图详解)
数据库·redis·缓存
永乐春秋1 小时前
WEB-通用漏洞&SQL注入&CTF&二次&堆叠&DNS带外
数据库·sql
打鱼又晒网2 小时前
【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析
数据库·mysql
大白要努力!2 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
tatasix2 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql
南城花随雪。3 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库