MySQL LEFT JOIN条件索引应该建在哪个表

酷强吖_1510

酷强吖_1510

2026-08-26

677人浏览

原创

left join索引必须建在右表on字段上,因左表为驱动表、右表为被驱动表,每次左表一行均需右表索引快速匹配;复合条件须按on顺序建联合索引,右表where条件应移入on子句避免退化为inner join。

mysql left join条件索引应该建在哪个表

LEFT JOIN 的索引必须建在右表(被驱动表)的 ON 字段上

LEFT JOIN 默认以左表为驱动表,右表是被驱动方——这意味着每次左表输出一行,MySQL 就要到右表里按 ON 条件查一次。如果右表没索引,就会全表扫描,10 万行驱动 × 100 万行右表 = 100 亿次行扫描。

常见错误是给左表加索引,比如 ALTER TABLE classes ADD INDEX idx_card(card),但 classes 是驱动表,有没有索引不影响它被全读;真正要加速的是右表 bookcard 字段:

ALTER TABLE book ADD INDEX idx_card(card);
  • 复合 ON 条件(如 ON t1.a = t2.x AND t1.b = t2.y)时,右表必须建联合索引 INDEX(x, y),顺序必须和 ON 中一致
  • INDEX(a, b, c) 无法加速 ON t2.b = ?,因为 b 不是最左前缀
  • 右表的 WHERE 条件字段(如 s.gender = 'F')如果写在 ON 子句里,也应包含进联合索引,比如 INDEX(class_id, gender)

LEFT JOIN 右表的 WHERE 条件不能写在 WHERE 子句里

把右表过滤条件放在 WHERE 会导致 LEFT JOIN 退化成 INNER JOIN。例如:

SELECT c.name, COUNT(s.id) FROM classes c LEFT JOIN students s ON c.id = s.class_id WHERE s.gender = 'F' GROUP BY c.name;

这条语句实际只返回有女学生的班级,其他班级被 WHERE 过滤掉了——因为 s.gender 是 NULL 时无法满足 = 'F'

正确做法是把右表条件移到 ON

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
SELECT c.name, COUNT(s.id) FROM classes c LEFT JOIN students s ON c.id = s.class_id AND s.gender = 'F' GROUP BY c.name;
  • 这样能保留所有班级,没女学生的班级计数为 0
  • 同时这个 AND s.gender = 'F' 让优化器更可能用上 INDEX(class_id, gender)
  • 如果仍用单列索引 INDEX(class_id)gender 过滤只能在内存中做,效率低

驱动表太大时,别硬扛,换思路

LEFT JOIN 左表是 50 万行,右表是 1 万行,但业务又要求左表必须是主表——这时候强行优化索引效果有限,得换执行逻辑:

  • 先用 WHERE 提前缩小左表结果集,比如加 WHERE c.status = 'active',让驱动行数从 50 万降到 5 千
  • 考虑用 EXISTS 替代仅判断存在的 LEFT JOIN,例如查“没有订单的客户”:
    SELECT * FROM customer c WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id)
  • 如果右表只需取一条最新记录(如最新订单时间),用相关子查询比 JOIN + GROUP BY 更稳:
    (SELECT created_at FROM orders o WHERE o.customer_id = c.id ORDER BY created_at DESC LIMIT 1)

STRAIGHT_JOIN 和 EXPLAIN 是你唯一能信的依据

别猜优化器怎么选驱动表,用 EXPLAINrows 列——它反映的是 WHERE 过滤后每张表预计扫描的行数,不是总行数。如果发现右表 rows 很大,说明它被当成了驱动表(比如用了 RIGHT JOIN 或嵌套子查询),或者索引根本没生效。

必要时用 STRAIGHT_JOIN 强制顺序,但只在确认估算准确时用:

SELECT STRAIGHT_JOIN c.name, s.name FROM classes c LEFT JOIN students s ON c.id = s.class_id;
  • STRAIGHT_JOIN 会忽略优化器成本估算,强制按书写顺序执行
  • 如果左表实际过滤后只剩 100 行,而优化器误判为 10 万行并选了右表当驱动,这时加 STRAIGHT_JOIN 反而更快
  • 但一旦估算错(比如统计信息过期),STRAIGHT_JOIN 会让性能雪崩,务必配合 ANALYZE TABLE 更新统计

最常被忽略的一点:字段类型不一致会直接让索引失效。比如 class_idINTs.class_idBIGINT,或一边是 VARCHAR 一边是 CHAR,MySQL 会隐式转换,导致右表索引完全不用。检查 SHOW CREATE TABLE,确保两边类型严格相同。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系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

3723

8

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

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

2023.10.27

791

4

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

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

2024.02.23

969

5

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

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

2024.03.06

5501

10

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

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

2024.03.06

2503

4

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

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

2024.04.07

5500

11

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

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

2024.04.29

7161

6

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

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

2024.04.29

970

5

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

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

2024.04.29

852

5

热门下载

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

精品课程

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

共1课时 | 170人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 274人学习