有大小表进行联表查询的时候,怎么优化?

2025年 阅读约 8 分钟 面试指南 · MySQL面试

深入解析MySQL大小表联表查询优化策略,包括小表驱动大表、索引优化、子查询优化等实战技巧。

一句话总结

大小表联表查询优化的核心原则是小表驱动大表,确保被驱动表关联字段有索引,先过滤再JOIN,避免SELECT *,必要时冗余字段或改用子查询。

初级理解

小表驱动大表:在JOIN操作中,MySQL优化器会自动选择小表作为驱动表。驱动表越小,外层循环次数越少,性能越好。

确保索引:被驱动表的关联字段必须有索引,否则会导致大表全表扫描。

-- 小表驱动大表示例 SELECT * FROM small_table s LEFT JOIN big_table b ON s.id = b.small_id WHERE s.status = 1;
一句话总结:小表驱动大表 + 被驱动表关联字段有索引 = 联表查询优化的基础。

中级深入

减少JOIN数据量:先过滤再JOIN,而非JOIN后再WHERE。

-- 优化前:先JOIN后过滤 SELECT * FROM small s JOIN big b ON s.id = b.sid WHERE s.status = 1; -- 优化后:先过滤后JOIN SELECT * FROM (SELECT * FROM small WHERE status = 1) s JOIN big b ON s.id = b.sid;

只查必要字段:避免SELECT *,减少IO和网络传输。

覆盖索引:让查询所需字段全部包含在索引中,避免回表。

注意:如果频繁JOIN,可以考虑将小表的关键字段冗余到大表中,避免JOIN操作。

高级拓展

子查询优化:优先使用JOIN替代子查询,MySQL对子查询优化有限。

-- IN子查询改写为JOIN -- 差 SELECT * FROM users WHERE id IN (SELECT user_id FROM orders); -- 好 SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id;

EXISTS vs IN:当外表小、内表大时,EXISTS可以利用内表索引快速返回。

派生表物化:MySQL 5.6+支持将子查询结果物化为临时表并加索引,但仍不如显式JOIN可控。

面试加分项:能说出小表驱动大表的原理、索引优化策略、子查询改写技巧,说明你对MySQL优化有深入理解。

实战场景

场景:电商订单表与用户表联表查询

-- 问题:订单表1000万,用户表100万,查询最近30天的订单及用户信息 -- 优化后:先过滤订单表(小表驱动大表) SELECT o.*, u.username, u.phone FROM (SELECT * FROM orders WHERE create_time > DATE_SUB(NOW(), INTERVAL 30 DAY)) o JOIN users u ON o.user_id = u.id;

面试模拟

Q:为什么LEFT JOIN时左表必须是小表?

A:因为LEFT JOIN的语义决定了左表是驱动表,MySQL会遍历左表每一行,然后去右表通过索引查找匹配行。驱动表越小,外层循环次数越少,性能越好。

Q:如何判断联表查询是否使用了索引?

A:使用EXPLAIN分析执行计划,重点关注type列(至少达到ref级别)、key列(是否命中索引)、rows列(扫描行数)。如果type为ALL,说明全表扫描,必须优化。