18人参与 • 2025-07-21 • Mysql
mysql 中的索引合并是一种查询优化技术,当单个表查询的 where
子句中包含多个条件,并且这些条件分别可以用到不同的索引时,mysql 优化器可能会尝试将这些索引扫描的结果合并起来,以更高效地获取最终满足所有条件的行。它本质上是优化器在无法找到最优的单个复合索引时的一种“折衷”策略。
核心思想: 利用多个索引分别筛选数据,然后将结果集合并(交集、并集或排序后并集)以得到最终结果,避免全表扫描。
mysql 主要支持三种索引合并算法:
适用场景: where
子句中的多个条件通过 and
连接,并且每个条件都可以有效地使用一个单独的索引(这些索引通常是单列索引)。
工作原理:优化器对每个可用的索引执行范围扫描或等值查询扫描。
示例:
create table `t` ( `id` int primary key, `a` int, `b` int, `c` varchar(100), index `idx_a` (`a`), index `idx_b` (`b`) ); -- 假设 idx_a 和 idx_b 都是 b-tree 索引 select * from t where a = 10 and b = 20;
idx_a
查找 a=10
的行(得到主键集合 s1)。idx_b
查找 b=20
的行(得到主键集合 s2)。type
列显示 index_merge
,extra
列显示 using intersect(idx_a, idx_b); using where
。适用场景: where
子句中的多个条件通过 or
连接,并且每个条件都可以有效地使用一个单独的索引(这些索引通常是单列索引),并且查询是 select
(非 update/delete
),并且没有使用 for update
或 lock in share mode
。
工作原理:
示例:
select * from t where a = 10 or b = 20;
idx_a
查找 a=10
的行(得到主键集合 s1)。idx_b
查找 b=20
的行(得到主键集合 s2)。type
列显示 index_merge
,extra
列显示 using union(idx_a, idx_b); using where
。适用场景: where
子句中的多个条件通过 or
连接,但是这些条件无法直接使用 index merge union
(通常是因为索引扫描返回的是范围结果,而不仅仅是点查询的等值结果)。它是 union
的一种变体,用于处理范围扫描。
工作原理:
示例:
select * from t where a < 10 or b < 20; -- 或者 select * from t where a < 10 or b = 20; -- 一个范围,一个等值
idx_a
扫描 a < 10
(得到主键集合 s1)。idx_b
扫描 b < 20
(或 b = 20
)(得到主键集合 s2)。type
列显示 index_merge
,extra
列显示 using sort_union(idx_a, idx_b); using where
。or
条件: 对于 or
连接的复杂条件,索引合并(特别是 sort_union
)提供了一种优化的执行路径。通常不如复合索引高效:
不是所有条件组合都适用:
and
/or
结构且每个条件都能独立使用索引时才可能触发。optimizer_switch
控制。例如:-- 查看当前设置 select @@optimizer_switch; -- 关闭所有索引合并优化 set optimizer_switch = 'index_merge=off'; -- 关闭特定类型的索引合并 (e.g., intersection) set optimizer_switch = 'index_merge_intersection=off';
需要确认相关标志(index_merge
, index_merge_intersection
, index_merge_union
, index_merge_sort_union
)是开启的 (on
)。
统计信息准确性: 优化器是否选择索引合并以及选择哪种合并算法,高度依赖于表的统计信息(如索引的基数 cardinality
)。过时的统计信息可能导致优化器做出错误的选择。
替代方案 - 优先考虑复合索引:
where
子句中的列,尤其是通过 and
连接的列,创建合适的复合索引通常是性能最优的选择。复合索引直接按索引顺序定位满足所有条件的行,避免了多索引扫描和合并的开销,也更容易避免回表(如果索引覆盖查询)。select * from t where a = 10 and b = 20;
,创建 index idx_a_b (a, b)
或 index idx_b_a (b, a)
通常会比依赖 idx_a
和 idx_b
的索引合并快得多。使用 explain
或 explain format=json
查看查询的执行计划:
type
列: 显示为 index_merge
。key
列: 列出实际使用的索引,多个索引用逗号分隔(如 idx_a, idx_b
)。extra
列: 明确指出使用的合并算法:using intersect(...)
(交集)using union(...)
(并集)using sort_union(...)
(排序并集)mysql 的索引合并(index merge)是一种在特定查询条件下(涉及多个索引列且条件由 and
或 or
连接),优化器利用多个独立索引分别扫描数据,然后对结果集进行交集、并集或排序后并集操作,最终定位目标行的优化策略。
intersect
处理 and
条件。union
/ sort_union
处理 or
条件(sort_union
处理范围扫描)。虽然索引合并提供了一种避免全表扫描的途径,但它通常伴随着额外的扫描、合并和回表开销。创建合适的复合索引(composite index)通常是解决这类查询性能问题的首选和更优方案,因为它能更直接、高效地定位数据。
到此这篇关于mysql索引合并的实现示例的文章就介绍到这了,更多相关mysql索引合并内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论