MySQL Join使用之大表关联小表及小表关联大表
目录
- 一、问题背景:为什么会问这个问题?
- 二、SQL Join 的执行javascript机制(mysql)
- 执行原理:
- 注意:
- 三、什么是大表?什么是小表?
- 四、大表驱动小表 vs 小表驱动大表:有何区别?
- 区别在于:驱动表每行都要去被驱动表中匹配一次
- 五、举例说明(含 SQL + 执行计划)
- 示例:订单表(大表) + 商品表(小表)
- 错误方式:大表驱动小表(性能差)
- 正确方式:小表驱动大表(性能优)
- 六、执行计划分析(EXPLAIN)
- 七、优化建议总结(面试可答)
- 1. 尽量使用小表做驱动表
- 2. 被驱动表要建好关联字段的索引
- 3. 尽量让 Join 条件包含等值匹配(=)
- 4. 避免 Join 条件计算、函数、隐式类型转换(会导致索引失效)
- 5. 使用STRAIGHT_JOIN强制 Join 顺序(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 小表驱动大表:有何区别?
区别在于:驱动表每行都要去被驱动表中匹配一次
驱动表越大,执行次数越多
被驱动表必须有合适http://www.devze.com的索引,否则每次匹配都全表扫
五、举例说明(含 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;
id | select_type | table | type | key | rows | Extra |
---|---|---|---|---|---|---|
1 | SIMPLE | o | ALL | NULL | 10,000,000 | |
1 | SIMPLE | p | ALL | NULL | 10,000 | Using 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 wDRdz的执行计划,关注 type 是否是 ALL(表示全表扫)、rows 是否偏大、key 是否命中索引等字段。如果必要,也会通过 STRAIGHT_JOIN 强制指定小表为驱动表。这个问题我在实际优化中遇到过好几次,比如商品表关联类目表、订单表关联用户表等场景。
九、思维导图版(简化复习)
大表 vs 小表关联问题
├── Join 执行原理:Nested Loop│ └── 左表为驱动表,右表为被驱动表├── 性能影响:│ ├── 驱动表大 → 循环次数多│ ├── 被驱动表无索引 → 每次全表扫├── 最佳实践:│ ├── 小表做驱动│ ├── 被驱动表建索引│ └── 使用 EXPLAIN 分析执行计划└── 补充技巧: ├── STRAIGHT_JOIN 控制顺序 ├── 避免函数/类型转换&http://www.devze.comnbsp; └── 等值 Join 优于范围 Join
总结
到此这篇关于MySQL Join使用之大表关联小表及小表关联大表的文章就介绍到这了,更多相关MySQL Join大表小表关联内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论