Skip to content

JOIN 连接:到底能不能写 JOIN?

很多开发同学下意识地认为 JOIN 会降低 SQL 性能,于是把多表查询拆成单表查询。但这样反而更慢——因为不了解 JOIN 的实现过程。

一、JOIN 的两种算法

MySQL 8.0 支持两种 JOIN 算法:

算法适用场景特点
Nested Loop JoinOLTP(小数据量、有索引)用索引逐行匹配
Hash JoinOLAP(大数据量、无索引)用哈希表批量匹配

1. Nested Loop Join

驱动表 R → 通过索引查询关联表 S

示例

sql
SELECT * FROM orders o 
INNER JOIN lineitem l ON o.o_orderkey = l.l_orderkey
WHERE o.o_orderdate >= '1994-02-01';

执行流程:

1. 用 idx_orderdate 过滤 orders(驱动表)
2. 对每条订单,用主键查 lineitem
3. 返回匹配结果

驱动表选择原则:谁过滤后的数据量少,谁就是驱动表。

2. Hash Join

扫描小表 → 创建哈希表 → 扫描大表 → 哈希匹配

适用于:没有索引数据量大的场景。

二、OLTP 能不能写 JOIN?

完全可以! 但要满足两个条件:

  1. WHERE 条件能过滤到少量数据
  2. JOIN 的列上有索引

示例(用户查订单):

sql
SELECT o_custkey, o_orderdate, o_totalprice, p_name 
FROM orders o, lineitem l, part p
WHERE o.o_orderkey = l.l_orderkey
  AND l.l_partkey = p.p_partkey
  AND o.o_custkey = ?      -- 用户ID过滤
ORDER BY o.o_orderdate DESC
LIMIT 30;

执行计划显示只扫描 30 条数据,无论表有多大,速度都很快

三、JOIN 使用建议

场景能否写 JOIN注意事项
OLTP(电商、支付)可以确保驱动表数据量少、有关联索引
OLAP(报表、分析)可以大数据量用 Hash Join
无索引关联慎用先加索引或考虑拆分成多次查询

核心原则:相信优化器,它比你更专业。确保索引到位,放心写 JOIN!