日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

MySQL优化器:index merge介绍

發(fā)布時間:2025/3/21 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL优化器:index merge介绍 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在MySQL官方手冊上,關(guān)于index merge的介紹非常非常少。甚至還有不少誤導(dǎo)的地方,這次把5.1版本關(guān)于此類優(yōu)化處理的代碼細看了一遍,以案例的方式介紹了各種實用index merge訪問類型的SQL。后續(xù)的還會繼續(xù)介紹index merge實現(xiàn)的主要數(shù)據(jù)結(jié)構(gòu),以及成本評估。

1. 什么是index merge

MySQL優(yōu)化器如果發(fā)現(xiàn)可以使用多個索引查找后的交集/并集定位數(shù)據(jù),那么MySQL優(yōu)化器就會嘗試index merge這類訪問方式。index merge主要分為兩大類,多個索引交集訪問(intersections),多個索引并集訪問,當(dāng)然這兩類還可以組合出更為復(fù)雜的方式,例如多個交集后做并集。

1.1 index merge的限制:range優(yōu)先

MySQL在5.6.7之前,使用index merge有一個重要的前提條件:沒有range可以使用。這個限制降低了MySQL index merge可以使用的場景。理想狀態(tài)是同時評估成本后然后做出選擇。因為這個限制,就有了下面這個已知的bad case(參考):

SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;

優(yōu)化器可以選擇使用goodkey1和goodkey2做index merge,也可以使用badkey做range。因為上面的原則,無論goodkey1和goodkey2的選擇度如何,MySQL都只會考慮range,而不會使用index merge的訪問方式。這是一個悲劇...(5.6.7版本針對此有修復(fù))

2. 關(guān)于index merge的一些案例

關(guān)于什么是交集/并集在手冊中有詳細介紹,這里不贅述。這里通過幾個案例來看看,哪些情況使用交集,哪些情況使用并集,哪些情況使用更復(fù)雜的組合。

示例中使用的表結(jié)構(gòu)和數(shù)據(jù)參考本文4.2節(jié)。

2.1 k1_p1 = 2 or k2_p1 = 4

這是最典型,也是最簡單的場景了:

SELECT * FROM tmp_index_merge where key1_part1 = 2 or key2_part1 = 4

explain SELECT * FROM tmp_index_merge where key1_part1 = 2 or key2_part1 = 4\G ...... table: tmp_index_merge type: index_merge key: ind1,ind2 key_len: 4,4 Extra: Using sort_union(ind1,ind2); Using where

2.2 (k1_p1=2 and k1_p2=7) or k2_p1=4\G

這個案例稍微復(fù)雜一丁點,第一個索引使用了兩個字段:

explain SELECT * FROM tmp_index_merge where (key1_part1 = 2 and key1_part2 = 7) or key2_part1 = 4\G ...... table: tmp_index_merge type: index_merge key: ind1,ind2 key_len: 8,4 Extra: Using sort_union(ind1,ind2); Using where

2.3 (k1_p1=2 or k1_p1=7) or k2_p1=4\G

這個案例也能夠使用index merge。內(nèi)部的實現(xiàn)比它表面上看起來要復(fù)雜,這里簡單解釋一下:MySQL在遞歸處理這個WHERE條件時,先處理前一部分(key1_part1 = 2 or key1_part1 = 7)。對于同一個索引的同一個字段進行or操作,MySQL會將其合并成一顆SEL_ARG樹(具體參考),兩個條件通過SEL_ARG的Next/prev指針連接。MySQL的range訪問方式可以通過遍歷這棵樹(也可以參考前面這篇文章)。接著優(yōu)化器再處理or的另一個分支(key2_part1 = 4)發(fā)現(xiàn)可以使用第二個索引,于是將index merge加入可能的執(zhí)行計劃列表(后續(xù)評估成本,再決定是否實用該訪問方式)。

explain SELECT * FROM tmp_index_merge where (key1_part1 = 2 or key1_part1 = 7) or key2_part1 = 4\G ...... table: tmp_index_merge type: index_merge key: ind1,ind2 key_len: 4,4 Extra: Using sort_union(ind1,ind2); Using where

2.4 (k1_p1=2 or k1_p2=7) or k2_p1=4\G

這種情況是無法直接使用任何索引的。不解釋。

explain SELECT * FROM tmp_index_merge where (key1_part1 = 2 or key1_part2 = 7) or key2_part1 = 4\G ...... table: tmp_index_merge type: ALL possible_keys: ind1,ind2 key: NULL Extra: Using where

2.5 k1_p1=1 or (k1_p1=2 and k1_p2=4 and k2_p1=3)

對于這樣的條件,MySQL會發(fā)現(xiàn)可以使用range訪問方式。而根據(jù)前面的"range優(yōu)先"原則,MySQL不再考慮index merge(這里k1_p1=1和k2_p1=3是可以通過index merge訪問方式實現(xiàn)的)。MySQL在考慮使用key1訪問的時候,看到的條件是:k1_p1=1 or (k1_p1=2 and k1_p2=4)。這里OR兩邊的條件可以構(gòu)造成一顆獨立的SEL_ARG。(本文后面小結(jié)“更多關(guān)于range優(yōu)先原則”有更多詳細介紹)

所以,MySQL會直接使用range,而不再考慮index merge。(怎樣的條件無法夠著成一顆SEL_ARG樹,參考,對于兩顆SEL_ARG通過or合并的時候,還有一些更復(fù)雜的事情,這里暫時不做介紹)

explain SELECT * FROM tmp_sel_tree where key1_part1=1 or (key1_part1=2 and key1_part2=4 and key2_part1=3)\G table: tmp_sel_tree type: range key: ind1 key_len: 8 Extra: Using where

如果前面這幾個案例看明白了,那可以繼續(xù)了,下面會有一些更復(fù)雜的案例:

2.6 嵌套的案例1

這個案例看起來很復(fù)雜,但其本質(zhì)跟最前面提到的"已知的bad case"相同,是一個可以使用index merge,但是被range優(yōu)先掉的案例。

SELECT * FROM tmp_sel_tree where ( key1_part1 = 1 or (key1_part2 = 2 and key2_part1 = 3) ) and ( key3_part1 = 5 )

2.7 嵌套的案例2

這個案例跟上面稍有不同,是一個三個索引的index merge,這里MySQL將考慮使用index merge。但是一般來說,這類index merge成本本身較大,容易超過全表的成本:

SELECT * FROM tmp_sel_tree where ( key1_part1 = 1 or (key1_part2 = 2 and key2_part1 = 3) ) or ( key3_part1 = 5 )

如果成本評估后,發(fā)現(xiàn)index merge成本小于全表,則會使用:

table: tmp_sel_tree type: index_merge key: ind1,ind2,ind3 Extra: Using sort_union(ind1,ind2,ind3); Using where

3. 更多關(guān)于range優(yōu)先原則

可以使用range的情況

在5.6.7之前的MySQL版本,只要可以使用Range訪問方式,那就不會再使用index merge。因為可以使用range訪問的WHERE條件是非常多的,除了我們常見的(k1_p1=const and k2_p2>const),如果參考Range優(yōu)化相關(guān)的數(shù)據(jù)結(jié)構(gòu),還會看到更多的WHERE條件可以使用range。

這里拿出其中一個較為復(fù)雜的可以使用range訪問的WHERE條件,做一個簡單分析。

WHERE ( key1_part1 = 3 and key1_part2 > 5 and key2_part1 = 7 ) or ( key1_part1 > 2 )

對于索引key2來說,這個條件可以簡化為如下,可以使用index merge的訪問方式:

(TRUE AND TRUE AND key2_part1 = 7) OR ( key1_part1 < 2 )

對于索引key1來說,條件簡化為:

(key1_part1 = 3 and key1_part2 > 5 and TRUE) or (key1_part1 > 2)

對于索引key1,這是一個可以使用range訪問方式的條件。根據(jù)前文Range優(yōu)化相關(guān)的數(shù)據(jù)結(jié)構(gòu)可以構(gòu)造成一顆SEL_ARG結(jié)構(gòu),如下:

$ $ SEL_ARG[2,∞) $ $ |^ $ $ next|| $ $ ||prev $ $ v| $ $ SEL_ARG[3,3] ==$====> SEL_ARG[5,∞] $ $ $

range訪問會依次SEL_ARG,遍歷訪問。因為有range訪問方式,所以這類條件不會再考慮index merge。

但如果WHERE是如下樣子(OR后面條件是key1_part2而不是key1_part1):

WHERE ( key1_part1 = 3 and key1_part2 > 5 and key2_part1 = 7 ) or ( key1_part2 > 2 )

OR后面的key1_part2是無法與前面的key1條件合并成一顆SEL_ARG樹,所以也就無法使用range訪問。因為or后面條件無法獨立使用索引訪問,所以也同樣無法做index merge訪問。

4. 其他

4.1 type in MySQL Explain

在MySQL手冊中把Explain中type列稱為:"EXPLAIN Join Types"。這給很多人產(chǎn)生了誤解,這里的Type實際是指在整個JOIN中這個單表的訪問方式。例如:

id: 1 select_type: SIMPLE table: tmp_sel_tree type: index_merge possible_keys: ind1,ind2,ind3 key: ind1,ind2,ind3 key_len: 4,4,4

常見的單表訪問方式有:const/ref/range/index/all

MySQL的優(yōu)化器主要有兩個自由度,一個是確定每個單表的訪問方式。另一個就是訪問順序。博客中常說的使用"range優(yōu)化" "index merge優(yōu)化"也是指MySQL單表訪問方式選擇了"range"或者"index merge"。

4.2 示例中的表結(jié)構(gòu)和數(shù)據(jù)

總結(jié)

以上是生活随笔為你收集整理的MySQL优化器:index merge介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。