using intersect表示mysql优化器对and等值条件使用多个单列索引同步扫描并取交集;它要求各字段均有独立索引、仅适用于等值查询,性能通常不如覆盖查询字段的联合索引,且mysql 8.0.19+默认禁用需手动开启。

Using intersect出现在EXPLAIN的Extra字段里说明什么
它不是语法错误,也不是你写错了SQL,而是MySQL优化器决定用多个二级索引“同步扫描 + 取交集”的方式执行WHERE中的AND条件。比如WHERE first_name = 'Aral' AND last_name = 'Masaki',当idx_fname和idx_lname都存在但没有联合索引时,就可能触发Using intersect。
关键点在于:这个策略只对AND连接的等值条件有效,且每个条件字段上必须有独立索引;它不适用于OR、范围查询(如>)、LIKE 'abc%'这类无法精确定位的条件。
为什么MySQL不用联合索引而选Using intersect
常见触发场景包括:
- 缺少覆盖所有WHERE字段的联合索引,但单列索引恰好都存在
- 联合索引的字段顺序不匹配查询条件(例如有
INDEX (a,b),但查询是WHERE b = ? AND a = ?) - 优化器预估单列索引各自过滤性很好,合并后比全表扫描或某一个索引+回表更优
注意:Using intersect需要各索引能独立定位到少量行,如果某个索引返回几万行,合并开销反而大,此时优化器通常会退回到ref或range访问类型。
Using intersect和联合索引哪个更快
一般情况下,设计合理的联合索引(如INDEX (first_name, last_name))比Using intersect更高效,原因有三:
- 只需一次B+树查找,避免多次索引扫描与内存中求交集的CPU开销
- 能天然支持
ORDER BY和GROUP BY,而Using intersect结果无序 - 减少回表次数——联合索引若覆盖查询字段(
Covering Index),可避免查主键再回聚簇索引
但如果你的查询条件动态组合多变(比如用户可选查first_name、last_name、birth_date中任意两个),建全量联合索引不现实,这时Using intersect反而是优化器在有限索引下的合理折中。
如何确认是否真走用了Using intersect
不能只看Extra字段,还要核对key和possible_keys:
-
key显示为NULL或某个单索引名,但possible_keys列出多个索引 → 很可能走了index merge - 执行
EXPLAIN FORMAT=JSON SELECT ...,检查used_key_parts是否为空,以及attached_condition是否被下推到各索引扫描层 - 对比加
FORCE INDEX指定联合索引后的rows和filtered值,差异明显说明优化器原策略不够优
真正容易被忽略的是:MySQL 8.0.19+默认禁用index merge(含Using intersect),需显式设置SET optimizer_switch='index_merge=on'才生效。线上环境若发现本该触发却没出现,先查这个开关。











