建一张有两个独立单列索引的表,验证OR条件触发Index Merge Union、AND条件触发Intersection,并测出比全表扫描快30倍。
a和b各自有自己的索引,互不相关,看OR/AND条件下优化器怎么用它们。
建表插入CREATE TABLE t16 (id INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, INDEX idx_a(a), INDEX idx_b(b)); 插入30万行,a、b各自随机1~1000
a=500 OR b=500,理论上没有一个联合索引能直接满足。
结果EXPLAIN SELECT * FROM t16 WHERE a=500 OR b=500 -> Filter: ((t16.a = 500) or (t16.b = 500)) -> Deduplicate rows sorted by row ID -> Index range scan on t16 using idx_a over (a = 500) (rows=295) -> Index range scan on t16 using idx_b over (b = 500) (rows=328)
的执行方式是:分别用idx_a和idx_b各自做一次独立的索引范围扫描,拿到两组的行ID集合,再Deduplicate rows sorted by row ID——按行ID排序去重合并,避免同时满足a=500和b=500的行被重复统计两次。这就是Index Merge的Union(并集)策略。
a=500 AND b=500,同样没有联合索引能一次搞定。
结果EXPLAIN SELECT * FROM t16 WHERE a=500 AND b=500 -> Filter: ((t16.b = 500) and (t16.a = 500)) -> Intersect rows sorted by row ID -> Index range scan on t16 using idx_a over (a = 500) (rows=295) -> Index range scan on t16 using idx_b over (b = 500) (rows=328)
这次是 Intersect rows sorted by row ID——两个索引各自找出满足单一条件的行ID集合,取交集,只留下同时满足两个条件的行。cost从Union的296降到了Intersect的0.77,因为交集通常比并集小得多。
用IGNORE INDEX强制对照。
结果Index Merge(OR条件,默认走法): actual time=0.0425..1.5 IGNORE INDEX强制全表扫描(同样OR条件): actual time=0.736..46
每一步都是本文上面用EXPLAIN和EXPLAIN ANALYZE跑出来的原始结果。
EXPLAIN / IGNORE INDEX:对比Index Merge和全表扫描