MySQL是如何决定JOIN查询中驱动表与被驱动表顺序的

酷墨吖_9530

酷墨吖_9530

2026-11-09

785人浏览

原创

驱动表由EXPLAIN中id最小的表决定,而非rows最小的表;INNER JOIN可重排顺序,LEFT JOIN因语义约束基本不可重排;统计信息不准会导致优化器误判,需定期ANALYZE TABLE;LEFT JOIN中应将右表过滤条件写入ON而非WHERE以实现下推。

mysql是如何决定join查询中驱动表与被驱动表顺序的

EXPLAIN里rows最小的表不一定是驱动表

很多人误以为EXPLAIN输出中rows值最小的表就是驱动表,其实不然。MySQL优化器看的是「过滤后参与JOIN的行数」,也就是rows × filtered的乘积。比如一张表rows = 10000但filtered = 1%,实际只有100行进入JOIN循环;另一张表rows = 500但filtered = 90%,反而有450行要被驱动——前者更可能被选为驱动表。

真正决定驱动关系的是执行计划中id列:id值越小,越早被访问,对应的就是驱动表。别只盯rows,要看id和type组合——如果第一个id的type是ALL或index,说明它在全表/全索引扫描,大概率就是驱动表,且很可能选错了。

INNER JOIN能重排,LEFT JOIN基本不能动

优化器对INNER JOIN有充分自由度:它会穷举所有left-deep连接顺序,基于成本估算挑最优解。但LEFT JOIN语义上锁死了左表必须全量保留,这极大限制了重排空间。即使右表数据少、索引好,优化器也不敢轻易把它提前,否则无法保证左表所有行都出现在结果里。

  • 如果你写的A LEFT JOIN B很慢,不要尝试改成B LEFT JOIN A——结果语义完全不同
  • 如果业务上其实不需要保留A中无匹配的NULL行,就该直接改成A INNER JOIN B,把选择权交还给优化器
  • STRAIGHT_JOIN在LEFT JOIN场景下基本无效,因为语义约束比成本估算更强

统计信息不准时,优化器会“信誓旦旦地选错”

MySQL优化器不读真实数据,只依赖采样估算。当出现以下情况时,它给出的rows和filtered可能严重失真:

  • 批量导入后没跑ANALYZE TABLE,索引基数还是旧的
  • 某字段存在严重数据倾斜(比如99%的status是'pending',但优化器按均匀分布估算)
  • InnoDB采样页数不足,默认只看8个叶子页,大表容易误判

这时你看到EXPLAIN里显示“驱动表只有100行”,实际执行扫了百万行——不是SQL写得不对,是优化器被统计信息骗了。临时解法是STRAIGHT_JOIN,长期解法是定期ANALYZE TABLE,必要时用FORCE INDEX配合调整。

Mysql Skill 1.0.0 (3)
Mysql Skill 1.0.0 (3)

MySQL 数据库管理技能,能够通过自然语言查询和管理数据库,支持 SELECT/INSERT/UPDATE/DELETE、表管理、备份恢复等操作。当用户提及 MySQL、数据库查询、建表或数据备份时使用此技能。

下载

ON里混WHERE条件,等于主动堵死优化器的路

把本该写在ON子句里的右表过滤条件挪到WHERE,表面看只是位置不同,实则彻底改变优化器的推理路径。例如:

SELECT * FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'shipped';

这条语句会让优化器认为:必须先拿到所有users,再为每行去orders查匹配,最后才筛status。哪怕orders.status有索引,也救不了JOIN阶段的全量探测。

正确做法是把过滤下推到ON里:

SELECT * FROM users u LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'shipped';

这样优化器就知道:右表只需加载status = 'shipped'的那部分数据,大幅缩小被驱动表的扫描范围。注意:这种改写只适用于LEFT JOIN,INNER JOIN下WHERE和ON效果等价,但习惯上仍建议把关联条件放ON、过滤条件放WHERE。

相关文章

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

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

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

2023.10.12

4863

8

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

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

2023.10.27

991

4

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

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

2024.02.23

1269

5

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

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

2024.03.06

6901

10

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

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

2024.03.06

3583

4

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

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

2024.04.07

6880

11

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

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

2024.04.29

9581

6

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

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

2024.04.29

1290

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1132

5

热门下载

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

精品课程

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

共1课时 | 194人学习