当前位置: 首页 > news >正文

SQL 查询慢?先从 EXPLAIN 看起

目录

什么是 EXPLAIN?​

EXPLAIN 输出字段详解​

1. type:访问类型​

2. key:使用的索引​

3. rows:估计要扫描的行数​

结合实例,用 EXPLAIN 优化多表关联查询​

总结​


在日常开发中,我们经常会遇到 SQL 查询变慢的情况。明明只是简单的查询,却要等上好几秒,严重影响了应用的性能。这时,很多人会下意识地去调整索引、修改 SQL 语句,但往往效果不佳。其实,想要优化 SQL 查询,首先要做的是了解查询的执行过程,而EXPLAIN 命令就是我们的 “透视镜”,它能帮我们看清 SQL 语句的执行计划,找到性能瓶颈所在。

什么是 EXPLAIN?​

EXPLAIN 是 MySQL 等关系型数据库提供的一个非常实用的命令,它可以模拟优化器执行 SQL 查询语句,从而让我们知道 MySQL 是如何处理 SQL 语句的。通过分析 EXPLAIN 输出的执行计划,我们可以了解到表的读取顺序、数据读取操作的类型、哪些索引被使用、表之间的连接方式等关键信息,进而针对性地进行优化。​

使用 EXPLAIN 非常简单,只需在要执行的 SQL 语句前加上 EXPLAIN 关键字即可,例如:

EXPLAIN SELECT * FROM student WHERE age > 20;

执行上述命令后,MySQL 会返回一张包含多个字段的表格,每个字段都代表着执行计划的不同信息。​

EXPLAIN 输出字段详解​

EXPLAIN 输出的字段有很多,其中type、key、rows这三个字段尤为重要,它们能帮助我们快速判断查询语句的性能瓶颈。​

1. type:访问类型​

type 字段表示 MySQL 在表中找到所需行的方式,也就是访问类型。它的取值从好到坏依次是:​

  • system:表中只有一行数据(系统表),这是 const 类型的特例,性能最好。​
  • const:表示通过索引一次就找到了,常用于主键或唯一索引查询。例如,根据主键查询某一行数据,type 就是 const。​
  • eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于多表关联查询中,使用主键或唯一索引作为关联条件。​
  • ref:非唯一性索引扫描,返回匹配某个单独值的所有行。例如,使用普通索引查询满足条件的行。​
  • range:只检索给定范围的行,使用索引来选择行。例如,使用 between、in 等关键字的查询。​
  • index:全索引扫描,遍历整个索引来获取数据。虽然比全表扫描快,但性能仍然较差。​
  • ALL:全表扫描,遍历整个表来找到匹配的行,性能最差。​

在实际开发中,我们要尽量避免出现 ALL 和 index 类型的访问,争取达到 ref 或更好的类型。​

2. key:使用的索引​

key 字段表示 MySQL 实际使用的索引。如果该字段为 NULL,则表示没有使用索引。这时候我们就要思考,是不是没有为查询条件中的字段建立索引,或者索引建立得不合理。​

例如,在查询 student 表中 age 大于 20 的学生时,如果 age 字段没有建立索引,key 字段就会为 NULL,查询会进行全表扫描;如果建立了索引,key 字段就会显示该索引的名称。​

3. rows:估计要扫描的行数​

rows 字段表示 MySQL 估计要执行查询时必须检查的行数。这个值越小,说明查询效率越高。需要注意的是,rows 是一个估计值,并不是实际值,但它能大致反映出查询的性能。​

如果 rows 的值很大,说明查询可能需要扫描大量的数据,这时候就需要考虑优化索引或修改查询语句了。​

除了上述三个关键字段外,EXPLAIN 输出的其他字段也有一定的参考价值,例如:​

  • id:表示查询中操作表的顺序,id 相同则执行顺序由上至下,id 不同则 id 值越大优先级越高。​
  • select_type:表示查询的类型,如简单查询、联合查询、子查询等。​
  • table:表示当前行正在访问的表的名称。​
  • possible_keys:表示可能使用的索引,但不一定会被实际使用。​
  • Extra:包含了很多额外的信息,如是否使用了临时表、是否进行了文件排序等,这些信息能帮助我们进一步分析查询性能。​

结合实例,用 EXPLAIN 优化多表关联查询​

下面我们结合学生表(student)和班级表(class)的例子,展示如何用 EXPLAIN 优化多表关联查询。​

表结构及数据​

学生表(student)结构:

CREATE TABLE student (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(20) NOT NULL,age INT,class_id INT,INDEX idx_class_id (class_id)
);

班级表(class)结构:

CREATE TABLE class (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(20) NOT NULL
);

假设 student 表中有 10000 条数据,class 表中有 100 条数据。​

未优化的多表关联查询​

现在我们需要查询所有年龄大于 20 的学生及其所在班级的名称,SQL 语句如下:

SELECT s.name, c.name 
FROM student s
JOIN class c ON s.class_id = c.id
WHERE s.age > 20;

我们用 EXPLAIN 来分析一下这个查询:

EXPLAIN
SELECT s.name, c.name 
FROM student s
JOIN class c ON s.class_id = c.id
WHERE s.age > 20;

执行结果可能如下(不同数据库环境可能会有差异):

id

select_type

table

1

SIMPLE

s

1

SIMPLE

c

从执行计划中可以看出:​

  • student 表的 type 是 ALL,说明进行了全表扫描,rows 为 10000,需要扫描大量数据。​
  • 虽然 student 表有 idx_class_id 索引,但在这个查询中没有被使用(key 为 NULL),因为查询条件是 age > 20,而 age 字段没有建立索引。​

优化查询​

针对上述问题,我们可以为 student 表的 age 字段建立索引:

CREATE INDEX idx_age ON student (age);

然后再用 EXPLAIN 分析查询:

EXPLAIN
SELECT s.name, c.name 
FROM student s
JOIN class c ON s.class_id = c.id
WHERE s.age > 20;

执行结果可能如下:

id

select_type

table

1

SIMPLE

s

1

SIMPLE

c

可以看到,优化后 student 表的 type 变为了 range,使用了 idx_age 索引(key 为 idx_age),rows 减少到了 2000,查询效率有了明显提升。​

这是因为建立 age 索引后,MySQL 可以通过索引快速定位到 age > 20 的学生记录,而不需要扫描整个表。​

总结​

EXPLAIN 命令是优化 SQL 查询的有力工具,通过分析它输出的执行计划,特别是 type、key、rows 等关键字段,我们可以快速找到查询语句的性能瓶颈。在进行多表关联查询时,合理地建立索引是提高查询效率的关键。​

当然,EXPLAIN 的使用还有很多细节需要我们去掌握,在实际开发中,我们要多动手实践,不断积累经验,才能写出高效的 SQL 语句。希望本文能帮助大家更好地理解和使用 EXPLAIN 命令,让 SQL 查询不再 “慢” 下来。​

http://www.dtcms.com/a/329576.html

相关文章:

  • 可视化调试LangChain SQLChatMessageHistory:SQLite数据库查看全攻略
  • 智算赋能:移动云助力“世界一流数据强港”建设之路
  • 什么是内外网文件传输?如何确保文件在内外网间安全、高效地传输呢?
  • 层次视觉 Transformer 与分布级特征精炼:面向多模态疾病诊断与机器遗忘的深度学习框架研究
  • [idekCTF 2025] diamond ticket
  • C#自定义日期时间选择器
  • 2025 电赛 C 题完整通关攻略:从单目标定到 2 cm 测距精度的全流程实战
  • C++编程学习(第22天)
  • k8s资源管理
  • 集成电路学习:什么是CV计算机视觉
  • 加密界的“瑞士军刀“-----VeraCrypt 加密原理与实操
  • 【数据结构】——栈(Stack)的原理与实现
  • iscc2025决赛wp
  • Redis面试精讲 Day 20:Redis大规模部署性能调优
  • MCP协议更新:从HTTP+SSE到Streamable HTTP,大模型通信的进化之路
  • [Oracle数据库] ORACLE的用户维护和权限操作
  • 多模态RAG赛题实战之策略优化--Datawhale AI夏令营
  • javaswing json格式化工具
  • 何解决PyCharm中pip install安装Python报错ModuleNotFoundError: No module named ‘json’问题
  • Day 39: 图像数据与显存
  • C++ stack and queue
  • Python3:使用venv虚拟环境
  • 猫头虎AI分享:Excel MCP,让AI具备操作Excel表格|创建销售数据表、复制工作表、填充数据、写公式、绘制图表、调节颜色、添加透视表、保存为PDF
  • Oracle数据库空间深度回收:从诊断到优化实战指南
  • Codeforces Round 1042 (Div. 3)
  • 友思特方案 | FPGA 加持,友思特图像采集卡高速预处理助力视觉系统运行提速增效
  • 【记录贴】STM32 I2C 控制 OLED 卡死?根源在 SR1 与 SR2 的读取操作
  • ELK开启安全策略
  • @系统管理 - Ansible 补丁管理方案(Windows Linux)
  • 从零开始:用PyTorch实现线性回归模型