mysql索引合并:一條sql可以使用多個(gè)索引

? ? ? ? ? 轉(zhuǎn)載請(qǐng)注明來(lái)源:mysql索引合并:一條sql可以使用多個(gè)索引

前言

mysql的索引合并并不是什么新特性。早在mysql5.0版本就已經(jīng)實(shí)現(xiàn)。之所以還寫這篇博文,是因?yàn)楹枚嗳诉€一直保留著一條sql語(yǔ)句只能使用一個(gè)索引的錯(cuò)誤觀念。本文會(huì)通過(guò)一些示例來(lái)說(shuō)明如何使用索引合并。

什么是索引合并

下面我們看下mysql文檔中對(duì)索引合并的說(shuō)明:

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、索引合并是把幾個(gè)索引的范圍掃描合并成一個(gè)索引。
2、索引合并的時(shí)候,會(huì)對(duì)索引進(jìn)行并集,交集或者先交集再并集操作,以便合并成一個(gè)索引。
3、這些需要合并的索引只能是一個(gè)表的。不能對(duì)多表進(jìn)行索引合并。

使用索引合并有啥收益

簡(jiǎn)單的說(shuō),索引合并,讓一條sql可以使用多個(gè)索引。對(duì)這些索引取交集,并集,或者先取交集再取并集。從而減少?gòu)臄?shù)據(jù)表中取數(shù)據(jù)的次數(shù),提高查詢效率。

怎么確定使用了索引合并

在使用explain對(duì)sql語(yǔ)句進(jìn)行操作時(shí),如果使用了索引合并,那么在輸出內(nèi)容的type列會(huì)顯示 index_merge,key列會(huì)顯示出所有使用的索引。如下:
mysql索引合并:一條sql可以使用多個(gè)索引

在explain的extra字段中會(huì)以下幾種:
Using union 索引取并集
Using sort_union 先對(duì)取出的數(shù)據(jù)按rowid排序,然后再取并集
Using intersect 索引取交集

你會(huì)發(fā)現(xiàn)并沒(méi)有 sort_intersect,因?yàn)楦鶕?jù)目前的實(shí)現(xiàn),想索引取交集,必須保證通過(guò)索引取出的數(shù)據(jù)順序和rowid順序是一致的。所以,也就沒(méi)必要sort了。

sort_union索引合并的示例

數(shù)據(jù)表結(jié)構(gòu)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@@######@@

數(shù)據(jù)

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

26

27

28

29

30

31

32

33

34

35

@@######@@

使用索引合并的案例

1

2

3

4

5

6

7

8

9

10

11

12

13

@@######@@

未使用索引合并的案例

1

2

3

4

5

6

7

8

9

10

11

12

13

@@######@@

sort_union總結(jié)

從上面的兩個(gè)案例大家可以發(fā)現(xiàn),相同模式的sql語(yǔ)句,可能有時(shí)能使用索引,有時(shí)不能使用索引。是否能使用索引,取決于mysql查詢優(yōu)化器對(duì)統(tǒng)計(jì)數(shù)據(jù)分析后,是否認(rèn)為使用索引更快。
因此,單純的討論一條sql是否可以使用索引有點(diǎn)片面,還需要考慮數(shù)據(jù)。

union索引合并使用案例

數(shù)據(jù)表結(jié)構(gòu)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@@######@@

數(shù)據(jù)結(jié)構(gòu)和之前有所調(diào)整。主要調(diào)整有如下兩方面:
1、引擎從myisam改為了innodb。
2、組合索引中增加了id,并把id放在最后。

數(shù)據(jù)

數(shù)據(jù)和上面的數(shù)據(jù)一樣。

使用索引合并的案例

1

2

3

4

5

6

7

8

9

10

11

12

13

@@######@@

union總結(jié)

相同的數(shù)據(jù),相同的sql語(yǔ)句,只是數(shù)據(jù)表結(jié)構(gòu)有所調(diào)整,就從sort_union變?yōu)榱藆nion。有以下幾個(gè)原因:
1、只要通過(guò)索引取出的數(shù)據(jù)已經(jīng)按rowid進(jìn)行了排序,就可以使用union。
2、組合索引中在最后加id字段,目的就是通過(guò)索引前兩個(gè)字段取出的數(shù)據(jù)是按id排序。
3、把引擎從myisam改為innodb,目的就是讓id和rowid的順序一致。

intersect使用案例

mysql索引合并:一條sql可以使用多個(gè)索引
http://www.php.cn/

以上就是mysql索引合并:一條sql可以使用多個(gè)索引的內(nèi)容,更多相關(guān)內(nèi)容請(qǐng)關(guān)注PHP中文網(wǎng)(www.php.cn)!

mysql>?show?create?table?testG  ***************************?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  1?row?in?set?(0.00?sec)
mysql>?select?*?from?test;  +----+------------+------------+------------+------------+  |?id?|?key1_part1?|?key1_part2?|?key2_part1?|?key2_part2?|  +----+------------+------------+------------+------------+  |??1?|??????????1?|??????????1?|??????????1?|??????????1?|  |??2?|??????????1?|??????????1?|??????????2?|??????????1?|  |??3?|??????????1?|??????????1?|??????????2?|??????????2?|  |??4?|??????????1?|??????????1?|??????????3?|??????????2?|  |??5?|??????????1?|??????????1?|??????????3?|??????????3?|  |??6?|??????????1?|??????????1?|??????????4?|??????????3?|  |??7?|??????????1?|??????????1?|??????????4?|??????????4?|  |??8?|??????????1?|??????????1?|??????????5?|??????????4?|  |??9?|??????????1?|??????????1?|??????????5?|??????????5?|  |?10?|??????????2?|??????????1?|??????????1?|??????????1?|  |?11?|??????????2?|??????????2?|??????????1?|??????????1?|  |?12?|??????????3?|??????????2?|??????????1?|??????????1?|  |?13?|??????????3?|??????????3?|??????????1?|??????????1?|  |?14?|??????????4?|??????????3?|??????????1?|??????????1?|  |?15?|??????????4?|??????????4?|??????????1?|??????????1?|  |?16?|??????????5?|??????????4?|??????????1?|??????????1?|  |?17?|??????????5?|??????????5?|??????????1?|??????????1?|  |?18?|??????????5?|??????????5?|??????????3?|??????????3?|  |?19?|??????????5?|??????????5?|??????????3?|??????????1?|  |?20?|??????????5?|??????????5?|??????????3?|??????????2?|  |?21?|??????????5?|??????????5?|??????????3?|??????????4?|  |?22?|??????????6?|??????????6?|??????????3?|??????????3?|  |?23?|??????????6?|??????????6?|??????????3?|??????????4?|  |?24?|??????????6?|??????????6?|??????????3?|??????????5?|  |?25?|??????????6?|??????????6?|??????????3?|??????????6?|  |?26?|??????????6?|??????????6?|??????????3?|??????????7?|  |?27?|??????????1?|??????????1?|??????????3?|??????????6?|  |?28?|??????????1?|??????????2?|??????????3?|??????????6?|  |?29?|??????????1?|??????????3?|??????????3?|??????????6?|  +----+------------+------------+------------+------------+  29?rows?in?set?(0.00?sec)
mysql>?explain?select?*?from?test?where?(key1_part1=4?and?key1_part2=4)?or?(key2_part1=4?and?key2_part2=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)
mysql>?explain?select?*?from?test?where?(key1_part1=1?and?key1_part2=1)?or?key2_part1=4G  ***************************?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)
mysql>?show?create?table?testG  ***************************?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`,`id`),  ??KEY?`key2`?(`key2_part1`,`key2_part2`,`id`)  )?ENGINE=InnoDB?AUTO_INCREMENT=30?DEFAULT?CHARSET=utf8  1?row?in?set?(0.00?sec)
mysql>?explain?select?*?from?test?where?(key1_part1=4?and?key1_part2=4)?or?(key2_part1=4?and?key2_part2=4)G  ***************************?1.?row?***************************  ???????????id:?1  ??select_type:?SIMPLE  ????????table:?test  ?????????type:?index_merge  possible_keys:?key1,key2  ??????????key:?key1,key2  ??????key_len:?8,8  ??????????ref:?NULL  ?????????rows:?2  ????????Extra:?Using?union(key1,key2);?Using?where  1?row?in?set?(0.00?sec)
? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊13 分享