MySQL Join使用之大表关联小表及小表关联大表

 更新时间:2025年08月18日 09:52:24   作者:自燃人~  
在MySQL中多表关联统计是一项常见的操作,特别是在数据分析和报表生成中,这篇文章主要介绍了MySQL Join使用之大表关联小表及小表关联大表的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、问题背景:为什么会问这个问题?

面试官问你这个问题,目的并不是让你说“哪个表放前哪个表放后”那么简单,而是考察你是否理解:

  • SQL Join 的执行原理(尤其是 Nested Loop Join);

  • 表的大小、顺序、索引对执行性能的影响;

  • 实战中有没有优化 Join 性能的经验;

  • 是否能借助 EXPLAIN 分析执行计划。

二、SQL Join 的执行机制(MySQL)

在 MySQL 中,主要使用的是 Nested Loop Join(嵌套循环连接)

执行原理:

for row in 外层表(驱动表):
    for row2 in 内层表(被驱动表):
        if row 与 row2 满足 join 条件:
            返回结果

注意:

  • SQL 写法中:SELECT * FROM A JOIN B ON ...
    默认是 A 为驱动表,B 为被驱动表。

  • 实际执行时,MySQL 可能会基于成本优化器调整顺序(通过 EXPLAIN 可见)。

三、什么是大表?什么是小表?

表类型行数(示意)特点
小表千行以内维度表、字典表、配置表等
大表万行、百万级交易表、日志表、订单表等

四、大表驱动小表 vs 小表驱动大表:有何区别?

区别在于:驱动表每行都要去被驱动表中匹配一次

  • 驱动表越大,执行次数越多

  • 被驱动表必须有合适的索引,否则每次匹配都全表扫

五、举例说明(含 SQL + 执行计划)

示例:订单表(大表) + 商品表(小表)

-- 大表:order (1000w)
-- 小表:product (1w)

错误方式:大表驱动小表(性能差)

SELECT * FROM order o
JOIN product p ON o.product_id = p.id;

执行逻辑:

  • 遍历订单表的每一行(1000w次)

  • 每一行去 product 中找匹配行

🔴 如果 product.id 无索引:每次都要全表扫描 product → 1000w × 1w → 超慢!

正确方式:小表驱动大表(性能优)

SELECT * FROM product p
JOIN order o ON  p.id =o.product_id;

执行逻辑:

  • 遍历 product 表的每一行(1w次)

  • 每次去 order 表查 product_id = xxx 的记录

    • order.product_id 有索引,则快速定位

性能大幅提升,尤其在 order 表是大表时。

六、执行计划分析(EXPLAIN)

EXPLAIN SELECT * FROM order o JOIN product p ON o.product_id = p.id; 
idselect_typetabletypekeyrowsExtra
1SIMPLEoALLNULL10,000,000
1SIMPLEpALLNULL10,000Using join buffer (Block Nested Loop)

🔴 都是全表扫描,说明没优化!

七、优化建议总结(面试可答)

1. 尽量使用小表做驱动表

  • 小表遍历次数少,整体性能高

2. 被驱动表要建好关联字段的索引

  • 没有索引就会退化成 Block Nested Loop + join buffer,耗时大

3. 尽量让 Join 条件包含等值匹配(=)

4. 避免 Join 条件计算、函数、隐式类型转换(会导致索引失效)

5. 使用STRAIGHT_JOIN强制 Join 顺序(MySQL 默认优化器可调换 Join 顺序)

SELECT * FROM small s STRAIGHT_JOIN big b ON s.id = b.id; 

八、真实面试回答模板(结构化)

我理解面试官这个问题主要是想考我是否清楚 Join 的执行原理以及实际优化经验。MySQL Join 默认使用的是嵌套循环(Nested Loop Join),左表作为驱动表,右表为被驱动表。我们在项目中一般优先选小表作为驱动表,被驱动表则需要建立好关联字段索引,这样可以大幅减少扫描次数,提升执行效率。如果大表做驱动表,而被驱动表没有索引,就可能出现成千上万次的全表扫描,性能会非常差。我们也会通过 EXPLAIN 查看 SQL 的执行计划,关注 type 是否是 ALL(表示全表扫)、rows 是否偏大、key 是否命中索引等字段。如果必要,也会通过 STRAIGHT_JOIN 强制指定小表为驱动表。这个问题我在实际优化中遇到过好几次,比如商品表关联类目表、订单表关联用户表等场景。

九、思维导图版(简化复习)

大表 vs 小表关联问题
├── Join 执行原理:Nested Loop
│   └── 左表为驱动表,右表为被驱动表
├── 性能影响:
│   ├── 驱动表大 → 循环次数多
│   ├── 被驱动表无索引 → 每次全表扫
├── 最佳实践:
│   ├── 小表做驱动
│   ├── 被驱动表建索引
│   └── 使用 EXPLAIN 分析执行计划
└── 补充技巧:
    ├── STRAIGHT_JOIN 控制顺序
    ├── 避免函数/类型转换
    └── 等值 Join 优于范围 Join

总结

到此这篇关于MySQL Join使用之大表关联小表及小表关联大表的文章就介绍到这了,更多相关MySQL Join大表小表关联内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql跨数据库复制表(在同一IP地址中)示例

    mysql跨数据库复制表(在同一IP地址中)示例

    这篇文章主要介绍了mysql跨数据库复制表(在同一IP地址中)示例,需要的朋友可以参考下
    2014-03-03
  • 详解Mysql 游标的用法及其作用

    详解Mysql 游标的用法及其作用

    这篇文章主要介绍了Mysql 游标的相关资料,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-09-09
  • MYSQL导入导出sql文件简析

    MYSQL导入导出sql文件简析

    这篇文章主要介绍了MYSQL导入导出.sql文件的相关资料,内容包括MYSQL的命令行模式的设置、命令行进入MYSQL的方法、数据库导出数据库文件、从外部文件导入数据到数据库,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • MYSQL 关于两个经纬度之间的距离由近及远排序

    MYSQL 关于两个经纬度之间的距离由近及远排序

    本篇文章是对MYSQL中关于两个经纬度之间的距离由近及远排序的方法进行了详细的分析介绍,需要的朋友参考下
    2013-07-07
  • MySQL定时备份数据库操作示例

    MySQL定时备份数据库操作示例

    这篇文章主要介绍了MySQL定时备份数据库操作,结合实例形式分析了MySQL定时备份数据库相关命令、原理、实现方法及操作注意事项,需要的朋友可以参考下
    2020-03-03
  • MySQL 设计和命令行模式下建立详解

    MySQL 设计和命令行模式下建立详解

    这篇文章主要介绍了MySQL 设计和命令行模式下建立详解的相关资料,主要讲解了数据库的建立与数据表的设计,需要的朋友可以参考下
    2017-01-01
  • MySQL使用ReplicationConnection导致连接失效解决

    MySQL使用ReplicationConnection导致连接失效解决

    这篇文章主要为大家介绍了MySQL使用ReplicationConnection导致连接失效问题分析解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 详解MySQL监控工具 mysql-monitor

    详解MySQL监控工具 mysql-monitor

    这篇文章主要介绍了解MySQL监控工具 mysql-monitor的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-07-07
  • MySQL必备基础之分组函数 聚合函数 分组查询详解

    MySQL必备基础之分组函数 聚合函数 分组查询详解

    这篇文章主要介绍了MySQL分组函数、聚合函数、分组查询,结合实例形式分析了MySQL查询分组函数以及查询聚合函数相关使用技巧,需要的朋友可以参考下
    2021-10-10
  • Mysql快速插入千万条数据的实战教程

    Mysql快速插入千万条数据的实战教程

    这篇文章主要给大家介绍了关于Mysql快速插入千万条数据的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03

最新评论