0

0

mysql中SELECT语句的执行流程与优化

P粉602998670

P粉602998670

发布时间:2026-01-07 07:23:36

|

484人浏览过

|

来源于php中文网

原创

MySQL执行SELECT语句的典型流程是:连接→查询缓存(8.0已移除)→解析→预处理→优化器→执行器→存储引擎层→返回结果,关键性能环节在优化器和存储引擎层。

mysql中select语句的执行流程与优化

SELECT 语句到底经过了哪些阶段?

MySQL 执行一条 SELECT 语句,不是直接去磁盘查数据,而是走一套有明确顺序的内部流程。理解这个流程,才能知道优化该从哪下手。

典型流程(以 InnoDB 为例)是:连接 → 查询缓存(8.0 已移除)→ 解析 → 预处理 → 优化器 → 执行器 → 存储引擎层 → 返回结果。其中真正影响性能的关键环节集中在「优化器」和「存储引擎层」。

  • MySQL 5.7 及以前:查询缓存可能成为性能陷阱——只要表有任意更新,整个表相关缓存全失效;8.0 直接删了 query_cache_type,不用再纠结是否开启
  • EXPLAIN 输出的 type 字段(如 ALLrangeref)反映的是优化器选择的访问类型,不是 SQL 写得“对不对”,而是“它认为怎么最快”
  • 执行器不负责数据读取,只调用存储引擎接口(如 ha_innobase::index_read()),真正的 I/O、加锁、MVCC 判断都在 InnoDB 层完成

为什么加了索引,EXPLAIN 还显示 type=ALL?

常见误解是“建了索引就一定走”,其实优化器会基于统计信息、索引选择性、WHERE 条件写法、隐式类型转换等综合判断。哪怕索引存在,也可能被跳过。

  • 对索引字段做函数操作:WHERE YEAR(create_time) = 2023 → 无法使用 create_time 上的普通 B+ 树索引
  • 隐式类型转换:WHERE user_id = '123'user_idINT)→ MySQL 转成数字比较,但可能导致索引失效(尤其在字符集不同或 collation 不一致时)
  • 联合索引未满足最左前缀:INDEX (a, b, c),但查询是 WHERE b = 2 AND c = 3 → 完全用不上该索引
  • 优化器估算全表扫描比走索引更快(比如查 80% 的行)→ 它真会选 ALL,这不是 bug,是成本计算结果

ORDER BY 和 LIMIT 怎么避免 filesort?

EXPLAINExtra 列出现 Using filesort,说明 MySQL 需要额外排序缓冲区,不是靠索引顺序直接返回结果。这在大数据量下极易拖慢响应。

hstshop鸿思特商城系统
hstshop鸿思特商城系统

鸿思特商城系统HstShop是一款B2C独立网店系统,由拥有十年互联网开发经验的牛头带队开发完成,完全免费开源,适合大中型网站平台快速构建立强大的网上商城平台网店系统。HstShop悉心听取每一位商家的需求与建议,根据中国人的购物习惯改进了购物流程,实现更好的用户购物体验。HstShop网店系统无论在产品功能、稳定性、执行效率、负载能力、安全性和搜索引擎优化等方面都居国内同类产品领先地位,成为国内

下载
  • 如果 ORDER BY 字段在索引中且顺序匹配,就能复用索引有序性。例如 INDEX (status, created_at),则 WHERE status = 1 ORDER BY created_at DESC 可免排序
  • ORDER BY a ASC, b DESC 在 MySQL 8.0+ 才支持混合方向索引(INDEX (a ASC, b DESC)),低版本只认统一方向
  • LIMIT 本身不触发 filesort,但和 ORDER BY 组合时,若没索引支撑,MySQL 仍需先排完所有匹配行再截断——所以 LIMIT 10 并不能让 ORDER BY 变快
  • 覆盖索引能进一步减少回表:比如 SELECT id, name FROM users WHERE status=1 ORDER BY created_at,可建 INDEX (status, created_at, id, name)

JOIN 为什么慢?驱动表选错是主因

MySQL 的 JOIN 是嵌套循环(Nested Loop),没有真正意义上的哈希连接(8.0.18+ 才在特定条件下用 Hash Join,但默认仍倾向 NLJ)。谁当驱动表(outer table),决定了外层循环次数和整体代价。

  • 优化器通常选「预估结果集更小」的表为驱动表。但统计信息不准(ANALYZE TABLE 没及时运行)、或条件写法干扰判断(如子查询、OR 条件),会导致选错
  • 强制指定驱动表可用 STRAIGHT_JOIN,但属高危操作——必须确认被驱动表有合适索引,否则性能雪崩
  • 小表驱动大表 ≠ 数据量小的表,而是「WHERE 条件过滤后结果集小」的表。比如用户表 100 万行,但 WHERE is_vip = 1 只返回 10 行,则它是理想驱动表
  • 关联字段类型/字符集不一致(如 utf8mb4_general_ci vs utf8mb4_0900_as_cs)会导致无法使用索引,JOIN 变成全表交叉
SELECT STRAIGHT_JOIN u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.is_vip = 1 AND o.status = 'paid';

真正难的不是写出快 SQL,而是看懂 EXPLAIN 里每个字段在说什么,以及明白 InnoDB 怎么把你的 SQL 翻译成页读取、行锁、间隙锁这些底层动作。很多“优化”失败,是因为在执行器层调优,而瓶颈其实在存储引擎的 Buffer Pool 命中率或 MVCC 版本链遍历上。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

676

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

346

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1092

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

356

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

674

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

571

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

412

2024.04.29

PPT动态图表制作教程大全
PPT动态图表制作教程大全

本专题整合了PPT动态图表制作相关教程,阅读专题下面的文章了解更多详细内容。

13

2026.01.07

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.6万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 783人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号