1. 什么是「小表驱动大表」?

驱动表 = 循环外层的表(少循环) 被驱动表 = 循环内层的表(快查)

原理就像两层 for 循环:

  1. // 小表驱动大表(快)
  2. for (小表100条) {
  3. 去大表100万条里索引查一下
  4. }
  5. 循环次数:100
  1. // 大表驱动小表(慢死)
  2. for (大表100万条) {
  3. 去小表100条里索引查一下
  4. }
  5. 循环次数:100万次

MySQL JOIN 优化器会自动选:数据量小的表当驱动表! 这就是 自动选择小表驱动大表


2. 那 IN 子查询 能不能做到小表驱动大表?

不能!至少不能稳定做到!

甚至 MySQL 会故意把它变成 大表驱动小表


3. 关键区别(核心)

JOIN

优化器会自动分析两张表大小 永远优先用小表驱动大表 内层被驱动表可以走索引,极快

IN (select …)

MySQL 优化器对子查询支持很弱 它会:

  1. 先执行子查询,生成一个临时结果集
  2. 再把主表 逐行 去匹配这个结果集

结果就是:

主表有多少行,就循环多少次! 主表如果 100 万行 → 循环 100 万次!

这就是 大表驱动小表(最差性能)


4. 最扎心的真相:IN 子查询的执行逻辑

你写的:

  1. select * from aaa where user_id in (select user_id from bbb where ...);

MySQL 实际执行 是:

  1. for (每一行数据 in aaa 表) {
  2. 判断 user_id 是否在 (子查询结果)
  3. }

aaa 表越大,这条 SQL 越慢!


5. 那 JOIN 是怎么执行的?

  1. select a.* from aaa a
  2. join bbb b on a.user_id = b.user_id
  3. where b.test <> 'hello';

MySQL 自动优化

  1. 看看 a 和 b 谁小
  2. 小表当驱动表(外层循环)
  3. 大表走索引(内层快速查找)

循环次数 = 小表行数,超级快!


6. 最直观对比(100万大表 vs 100行小表)

方式 驱动方式 循环次数 性能
INNER JOIN 小表驱动大表 100 极快
IN 子查询 大表驱动小表 100万 极慢

7. 那 EXISTS 呢?

  1. select * from aaa a
  2. where exists (select 1 from bbb b where b.user_id = a.user_id);

EXISTS 会自动小表驱动大表,性能 ≈ JOIN写法不如 JOIN 直观


8. 最终结论(开发必背)

  1. JOIN 会自动小表驱动大表,性能最好
  2. IN 子查询无法稳定小表驱动大表
  3. 数据量越大,IN 越慢,JOIN 优势越大
  4. 千万不要在大表上使用 IN (select …)
  5. 所有关联查询,优先用 JOIN

超级总结

  • JOIN = 自动小表驱动大表 = 快
  • IN 子查询 = 大表驱动小表 = 慢

用看 EXPLAIN 执行计划,一眼看到驱动表是谁。