MySQL关联查询中需为关联双方字段都创建索引吗?
MySQL JOIN 时的索引使用分析
咱们先从MySQL处理JOIN的核心逻辑说起——它最常用的是Nested Loop Join(嵌套循环连接),简单说就是先选一个表当「驱动表」,遍历它的每一行数据,再用JOIN条件里的字段去另一个「被驱动表」里找匹配的行。所以索引的使用完全取决于这个执行计划的选择。
关于你的问题:是否仅需给table_foo.foo_id建索引?
答案是不一定,MySQL可能只用其中一个索引,也可能同时用到两个,具体看执行计划和表的数据分布:
1. 常见场景:小表当驱动表
MySQL通常会自动选择数据量更小的表作为驱动表(减少外层循环的次数):
- 如果
table_foo是驱动表:
给table_foo.foo_id建索引,除非你有额外的过滤条件(比如WHERE子句),否则对于SELECT *这种全字段查询,驱动表大概率还是会走全表扫描(因为索引覆盖不了所有字段,回表成本可能更高)。这时候更关键的是给table_bar.bar_id建索引——这样每拿到驱动表的一个foo_id,就能快速在table_bar里定位匹配的行,避免全表扫描table_bar。 - 如果
table_bar是驱动表:
同理,table_bar.bar_id的索引可能帮驱动表优化扫描,而table_foo.foo_id的索引则用来快速匹配JOIN条件。
2. 如何从EXPLAIN结果判断?
你提到了EXPLAIN结果,咱们看几个核心字段就能明确:
type列:如果某张表的type是ref或eq_ref,说明该表用到了索引做匹配;如果是ALL,就是全表扫描。key列:直接显示该表实际用到的索引名称,如果两个表的key都有值,说明同时使用了两个索引;如果只有一个有值,就只用了那个索引。rows列:预估的扫描行数,行数越少说明索引生效的效果越好。
总结建议
- 最优方案是给
table_foo.foo_id和table_bar.bar_id都建立索引,尤其是当其中一张表数据量较大时,能大幅降低JOIN的时间成本。 - 如果只能二选一,优先给被驱动表的JOIN字段建索引——因为驱动表每一行都要去被驱动表查找,索引能把单次查找从全表扫描的O(n)降到O(log n),提升效果更明显。
内容的提问来源于stack exchange,提问作者Taichi
相关产品推荐
相关产品推荐

