MySQL 索引合并(Index Merge)优化

本文问题

  1. 什么是Index MergeIndex Merge的限制有哪些?
  2. 如何查看语句是否使用了Index Merger
  3. Index Merge有哪几种?分别适用于那些情景?
  4. 如何控制优化器是否使用Index Merge

Index Merge 索引合并

索引合并检索方法可以检索多个范围扫描并将结果合并。这种访问方法只能合并同一个表的索引扫描,不能合并跨表扫描。
合并可能生成基础扫描结果的"并集","交集",或者"交集的并集"

示例:

SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;

SELECT * FROM tbl_name
  WHERE (key1 = 10 OR key2 = 20) AND non_key = 30;

SELECT * FROM t1, t2
  WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')
  AND t2.key1 = t1.some_col;

SELECT * FROM t1, t2
  WHERE t1.key1 = 1
  AND (t2.key1 = t1.some_col OR t2.key2 = t1.some_col2);

Index Merge的已知缺陷

  • 如果在WHERE语句中,存在多层嵌套的AND/OR,MySQL可能不会选择最优的方案,可以尝试通过拆分WHERE子句的条件来进行转换:
(x AND y) OR z => (x OR z) AND (y OR z)
(x OR y) AND z => (x AND z) OR (y AND z)
  • Index Merger不能应用于全文索引(fulltext index

Index Merge的EXPLAIN输出

  • type列的值显示为index_merge
  • key列显示使用的索引列表
  • key_len列显示这些索引的最大长度(列表)。
  • Extra列显示Index Merge的算法:
    • Using intersect(...)
    • Using union(...)
    • Using sort_union(...)
mysql> explain select * from test_merge where (col1<10 and col2>50) or col3=50;
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+----------------------------------------------+
| id | select_type | table      | partitions | type        | possible_keys | key           | key_len | ref  | rows | filtered | Extra                                        |
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+----------------------------------------------+
|  1 | SIMPLE      | test_merge | NULL       | index_merge | idx_1_2,idx_3 | idx_1_2,idx_3 | 5,5     | NULL |  214 |   100.00 | Using sort_union(idx_1_2,idx_3); Using where |
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+----------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from test_merge where (col1=10 and col2=50) or col3=50;
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+-----------------------------------------+
| id | select_type | table      | partitions | type        | possible_keys | key           | key_len | ref  | rows | filtered | Extra                                   |
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+-----------------------------------------+
|  1 | SIMPLE      | test_merge | NULL       | index_merge | idx_1_2,idx_3 | idx_1_2,idx_3 | 10,5    | NULL |   22 |   100.00 | Using union(idx_1_2,idx_3); Using where |
+----+-------------+------------+------------+-------------+---------------+---------------+---------+------+------+----------+-----------------------------------------+
1 row in set, 1 warning (0.00 sec)

Index Merge 算法

Index Merge Intersection 索引合并交集

这种方法适用于WHERE子句中的条件是通过AND结合的不同索引的范围条件时,其中的每个条件都需要满足下列条件之一:

  • 如果其中的索引是多列索引,条件中需要包括索引的所有列
    key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN
  • Innodb表的主键上的范围条件

示例:

SELECT * FROM innodb_table
  WHERE primary_key < 10 AND key_col1 = 20;

SELECT * FROM tbl_name
  WHERE key1_part1 = 1 AND key1_part2 = 2 AND key2 = 2;

索引合并交集算法在所有使用的索引上同时进行扫描,并从扫描结果中生成行的交集
如果查询中的所有列都被使用的索引覆盖,不需要检索所有表行(EXPLAIN输出中的Extra列中包括Using index)。例如这个语句:
SELECT COUNT(*) FROM t1 WHERE key1 = 1 AND key2 = 1;

如果使用的索引没有覆盖查询中所有的行,只有当所有使用的索引的范围条件满足时才检索整个行。
如果合并条件中包括Innodb表主键索引条件,主键并不用来检索数据,而是用来筛选使用其他条件检索出的行。 # 就是先通过其他的范围条件筛选出一部分数据,在从这部分数据中,通过主键来筛选出最终的结果

Index Merge Union 索引合并并集

这种方法适用于WHERE子句中的条件是通过OR结合的不同索引的范围条件时,其中的每个条件都需要满足下列条件之一:

  • 如果其中的索引是多列索引,条件中需要包括索引的所有列
    key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN
  • Innodb表的主键上的范围条件
  • 适用于Index Merger intersection算法的条件

示例:

SELECT * FROM t1
  WHERE key1 = 1 OR key2 = 2 OR key3 = 3;

SELECT * FROM innodb_table
  WHERE (key1 = 1 AND key2 = 2)
     OR (key3 = 'foo' AND key4 = 'bar') AND key5 = 5;

Index Merge Sort_Union

这种方法适用于WHERE子句中的条件是通过OR结合的不同索引的范围条件,但是不能使用Index Merge Union算法的情景
示例:

SELECT * FROM tbl_name
  WHERE key_col1 < 10 OR key_col2 < 20;

SELECT * FROM tbl_name
  WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col = 30;

sort_unionunion算法的区别是,sort_union必须在返回行数据前先获取行ID并对行ID进行排序。

禁用Index Merge

optimizer_swith中有4个关于Index Merge的变量:
index_merge,index_merge_intersection,index_merge_union,index_merge_sort_union
默认情况下都是启用的。要单独启用某个算法,设置index_merge=off,并将相应的标志设置为on

问题答案

  1. 什么是Index MergeIndex Merge的限制有哪些?
    如果查询中使用到了不同的索引,可以对不同索引的条件分别进行范围扫描,然后将扫描结果合并得到最终的结果,这就是Index Merge
    限制:只能合并同一个表的索引扫描结果,不能跨表合并。此外,无法对fulltext索引进行合并
  2. 如何查看语句是否使用了Index Merge
    EXPLAINtype列的值为index_merge表示使用了索引合并。根据索引合并算法的不同,会在Extra列中显示Using intersect/union/sort_union
  3. Index Merge有哪几种?分别适用于那些情景?
    3种:Intersection,Union,Sort_union
    Intersection:使用AND结合的关于不同索引的条件(普通索引的等值表达式或者主键索引的范围表达式)
    UnionSort Union:使用OR结合的关于不同索引的范围条件
    区别:当条件为普通索引的等值表达式或者主键索引的范围表达式时,可以使用Union。其他不符合条件的只能使用Sort Union
    如果包括多列索引,在范围条件中需要包括索引中的所有列。
  4. 如何控制优化器是否使用Index Merge
    optimizer_swith中有4个关于Index Merge的变量:
    index_merge,index_merge_intersection,index_merge_union,index_merge_sort_union
    默认情况下都是启用的。要单独启用某个算法,设置index_merge=off,并将相应的标志设置为on
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335