惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 郭慕荣

Docker部署zookeeper总结 Mac中git ssh的配置(GitLab) Java 类加载机制 面试题(一) 如何监控和调优JVM性能? jvm常用的参数有哪些? 怎么配置? hashmap 和currenthashmap 的原理?详解一下 aop在项目中使用的场景?怎么使用? Java dubbo spring springboot中的spi机制 spring中常见的两种代理模式 Redis的zset 面试汇总 drools 规则引擎在线化配置 - 郭慕荣 springcloud中常用的注解详解 springcloud中网关gateway总结 spring是怎么解决循环依赖的? MySQL 死锁 怎么处理? 在写left join的时候 是大表在左侧 还是小表在左侧(一) nacos客户端(接口调用者)如何感知被调用服务下线? (二) nacos客户端(接口调用者)如何感知被调用服务下线?(一) 在MySQL中 redolog undolog binlog 写入的场景,顺序 - 郭慕荣
在写left join的时候 是大表在左侧 还是小表在左侧(二)
郭慕荣 · 2025-10-21 · via 博客园 - 郭慕荣

在 SQL 中使用 LEFT JOIN 时,左表(左侧的表)的选择不仅影响结果集的完整性,还直接决定了查询性能。核心原则是:在满足业务逻辑的前提下,优先让小表作为左表,大表作为右表。但需注意,这一结论的前提是 “业务逻辑允许”—— 因为 LEFT JOIN 的核心是 “保留左表的所有记录,右表匹配不到则补 NULL”,左表的选择首先必须符合业务对结果集的要求(即需要完整保留哪些数据)。

LEFT JOIN 的执行效率与左表(驱动表)的大小、右表(被驱动表)的索引 / 大小密切相关,具体原因如下:

LEFT JOIN 的执行逻辑是:先遍历左表的所有行,再逐行到右表中匹配符合条件的记录。因此,左表的行数直接决定了 “需要执行多少次匹配操作”。

  • 若左表是小表(如 10 万行),则只需执行 10 万次匹配;
  • 若左表是大表(如 1 亿行),则需执行 1 亿次匹配,即使每次匹配效率很高,总耗时也会显著增加。

示例:假设左表 A 有 100 万行,右表 B 有 1 亿行,LEFT JOIN A ON B 需执行 100 万次匹配;若反过来 LEFT JOIN B ON A,则需执行 1 亿次匹配,后者的基础匹配次数是前者的 100 倍,性能差距悬殊。

右表的匹配效率取决于是否有合适的索引。大表通常会为连接字段(ON 后的条件字段)建立索引(否则全表扫描成本极高),而小表即使没有索引,全表扫描的成本也很低(因为数据量小)。

  • 若右表是大表且有索引:每次匹配可通过索引快速定位(如 B+ 树索引,单次查询时间复杂度 O (logN)),即使左表是小表,整体效率也很高;
  • 若右表是小表:即使没有索引,全表扫描(O (N))的成本也可接受(比如小表只有 1 万行,全表扫描 1 万次对数据库压力很小)。

反例:若左表是大表,右表是小表且无索引,此时左表的每一行都需要对右表做全表扫描,总耗时 = 大表行数 × 小表行数,性能会急剧下降(例如 1 亿 × 1 万 = 10 万亿次操作,完全不可接受)。

LEFT JOIN 的结果集行数 至少等于左表行数(右表匹配不到时补 NULL)。

  • 若左表是小表:结果集行数较少(如 10 万行),内存 / 磁盘存储压力小,后续处理(如排序、聚合)效率高;
  • 若左表是大表:结果集行数至少是大表行数(如 1 亿行),可能导致内存溢出(OOM)或磁盘临时文件暴涨,拖慢整个查询。

LEFT JOIN 的左表选择不能仅看性能,必须优先满足业务需求。例如:

  • 需查询 “所有用户的订单记录(包括没有订单的用户)”,此时 用户表 必须作为左表(即使 用户表 是大表,订单表 是小表);
  • 需查询 “所有商品的销售数据(包括未销售的商品)”,商品表 必须作为左表(无论大小)。

这种情况下,只能接受大表作为左表,但可通过以下方式优化性能:

  1. 给右表的连接字段建立索引(如 订单表.user_id),减少匹配耗时;
  2. 对左表进行过滤(如 WHERE 左表.日期 > '2023-01-01'),减少左表的实际行数;
  3. 避免在 LEFT JOIN 后使用 SELECT *,只查询必要字段,减少数据传输和存储成本。

部分数据库(如 PostgreSQL、Oracle)的优化器会对 JOIN 进行 “重排序”,但 LEFT JOIN 因语义限制(必须保留左表所有行),优化器无法交换左右表顺序。例如:

  • A LEFT JOIN B 中,优化器必须以 A 为驱动表,无法自动将 B 作为驱动表(即使 B 更小)。

而 MySQL 的优化器对 LEFT JOIN 的重排序限制更严格,几乎完全遵循用户指定的顺序。因此,用户必须主动选择更优的左表,不能依赖优化器自动调整。

  1. 业务优先:左表必须是 “需要完整保留所有记录” 的表(如 “用户表”“商品表”),这是 LEFT JOIN 的语义决定的;
  2. 性能优化:在满足业务的前提下,优先选择小表作为左表,大表作为右表,理由是:
    • 减少驱动表的行数,降低匹配次数;
    • 大表作为右表时,更易通过索引优化匹配效率;
    • 控制结果集大小,减少资源消耗。

一句话结论:先看业务需要保留哪个表的全部数据,再在这个前提下,选小的那个表做左表。