余瑜的博客 余瑜的博客
首页
  • 并发
  • 线程池
  • spring
  • maven
  • 其他
  • redis
  • mysql
  • linux
  • zookeeper
  • docker
  • terminal
  • kong插件开发
  • 资料
  • leetCode-简单
  • blog
  • 其他
关于
GitHub (opens new window)
首页
  • 并发
  • 线程池
  • spring
  • maven
  • 其他
  • redis
  • mysql
  • linux
  • zookeeper
  • docker
  • terminal
  • kong插件开发
  • 资料
  • leetCode-简单
  • blog
  • 其他
关于
GitHub (opens new window)
  • redis

  • mysql

    • 高性能mysql学习笔记
    • MySQL中的函数
    • InnoDB和MyISAM区别
    • mysql索引最左原则
    • b+树图文详解
    • 聚集索引与辅助索引
    • 索引合并
      • 怎么确定使用了索引合并?
        • 使用索引合并的案例
        • 未使用索引合并的案例
      • 注意事项
  • DB
  • mysql
余瑜
2019-06-18
目录

索引合并

# 索引合并

转载自 (opens new window)

The Index Merge method is used to retrieve rows with several range scans and to merge their results into one. The merge can produce unions, intersections, or unions-of-intersections of its underlying scans. This access method merges index scans from a single table; it does not merge scans across multiple tables.

  1. 索引合并是把几个索引的范围扫描合并成一个索引。
  2. 索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。
  3. 这些需要合并的索引只能是一个表的。不能对多表进行索引合并。

# 怎么确定使用了索引合并?

在使用explain对sql语句进行操作时,如果使用了索引合并,那么在输出内容的type列会显示 index_merge,key列会显示出所有使用的索引。如下:
使用索引合并的示例

mysql> show create table test\G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key1_part1` int(11) NOT NULL DEFAULT '0',
  `key1_part2` int(11) NOT NULL DEFAULT '0',
  `key2_part1` int(11) NOT NULL DEFAULT '0',
  `key2_part2` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `key1` (`key1_part1`,`key1_part2`),
  KEY `key2` (`key2_part1`,`key2_part2`)
) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8
row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 使用索引合并的案例

mysql> explain select * from test where (key1_part1=4 and key1_part2=4) or key2_part1=4\G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: test

         type: index_merge

possible_keys: key1,key2

          key: key1,key2

      key_len: 8,4

          ref: NULL

         rows: 3

        Extra: Using sort_union(key1,key2); Using where

1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 未使用索引合并的案例

mysql> explain select * from test where (key1_part1=1 and key1_part2=1) or key2_part1=4\G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: test

         type: ALL

possible_keys: key1,key2

          key: NULL

      key_len: NULL

          ref: NULL

         rows: 29

        Extra: Using where

1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

从上面的两个案例大家可以发现,相同模式的sql语句,可能有时能使用索引,有时不能使用索引。是否能使用索引,取决于mysql查询优化器对统计数据分析后,是否认为使用索引更快。因此,单纯的讨论一条sql是否可以使用索引有点片面,还需要考虑数据。

# 注意事项

mysql5.6.7之前的版本遵守range优先的原则。也就是说,当一个索引的一个连续段,包含所有符合查询要求的数据时,哪怕索引合并能提供效率,也不再使用索引合并。举个例子:

mysql> explain select * from test where (key1_part1=1 and key1_part2=1) and key2_part1=1\G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: test

         type: ref

possible_keys: key1,key2

          key: key2

      key_len: 4

          ref: const

         rows: 9

        Extra: Using where

1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

上面符合查询要求的结果只有一条,而这一条记录被索引key2所包含。
可以看到这条sql语句使用了key2索引。但是这个并不是最快的执行方式。其实,把索引key1和索引key2进行索引合并,取交集后,就发现只有一条记录适合。应该查询效率会更快。

上次更新: 2021/02/16, 15:47:09

← 聚集索引与辅助索引

Theme by Vdoing | Copyright © 2018-2022 逆光世间 | 备案号: 京ICP备19016086号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式