復雜sql分析 以及 索引合并

復雜sql分析

簡單的sql語句我們很簡單的就可以分析出來它的執行計劃,但是復雜的sql呢。例如

SELECT	*	FROM	single_table	WHERE(key1	>	'xyz'	AND	key2	=	748	)	OR(key1	<	'abc'	AND	key1	>	'lmn')	OR(key1	LIKE	'%suf'	AND	key1	>	'zzz'	AND	(key2	<	8000	OR	common_field	=	'abc'))	;

這條語句很難分析出來,遇到這樣的語句怎么辦呢,怎么分析它的范圍匹配區間呢?

首先我們在為某個索引確定范圍區間的時候只需要把用不到相關索引的搜索條件替換成true。

之所以把用不到索引的搜索條件替換為true,是因為我們呢不打算使用這些條件進行在該索引上進行過濾,所以不管索引的記錄滿不滿足這些條件,我們都把他們選取出來,帶到之后徽標的時候再使用他們過濾。

例如select * from table where key1 >100 and key2 > 10;

如果假設為用key1上的索引就可以簡化為:select * from table where key1 > 100 and true;

如果假設為用key2上的索引就可以簡化為:select * from table where true and key2 > 10;

根據小學的知識:a? and? b? ?只有a和b同時為true的時候結果才為true,只有所以key1>100 and true 可以簡化為key1 > 100,因為最后的結果由key1 > 100決定。

所以如果假設為用key1上的索引就可以簡化為:select * from table where key1 > 100;

根據上面的方法就可以簡化上面的復雜sql為:

我們假設使用key1上的索引。

①key1 < 'abc' AND key1 > 'lmn',永遠都不會滿足這個條件,所以為false

②key1 like ‘%suf'? 因為%在前面所以這個條件是用不到索引的

SELECT	*	FROM	single_table	WHERE(key1	>	'xyz'	AND	true	)	OR(false)	OR(true	AND	key1	>	'zzz'	AND	(true	OR	true))	;

false or 條件? ? ? ?根據小學的知識,最后的結果取決與條件為true還是false,所以簡化為:條件?

SELECT	*	FROM	single_table	WHEREkey1	>	'xyz'	OR  key1	>	'zzz';

這就變成了簡單的sql。可以很好的進行分析

繼續簡化因為條件為or,所以最后的結果取并集,所以就是最小的值key1 > 'xyz'

我們假設使用key2上的索引。

SELECT	*	FROM	single_table	WHEREkey2 = 748  or true	;

true? or? ?任何條件的結果:true

所以使用key2?需要掃描key2二級索引的全部記錄,然后回表,這效率很低甚至不如全表掃描,所以優化器最后選擇key1上的索引。

索引合并

mysql在一般的情況下執行一個查詢最多會用到單個二級索引,但是也有些特上述情況可能用到多個二級索引,mysql中把這種使用到多個索引來完成一次查詢的執行方法稱之為:index_merge

explain的type = index_merge

索引合并有三種算法

Intersection合并

intersection就是交集的意思,就是某個查詢可以使用多個二級索引,將多個二級索引中查到的結果取交集,例如

select * from table where key1 = 'a' and key2 = 'b';
假設使用intersection算法就是:

①從key1二級索引的B+樹中取出key1=’a'的記錄

②從key2?二級索引的B+樹中取出key2=’a'的記錄

③二級索引都是由二級索引列+id值組成,所以我們可以計算出兩個結果集中id值的交集

④根據交集的id值進行回表操作,把結果返回給用戶。

這?有同學會思考:為啥不直接使?idx_key1或者idx_key3只根據某個搜索條件去讀取?個?級索引,然后回表后再過濾另外?個搜索條件呢?這?要分析?下 兩種查詢執??式之間需要的成本代價。

只讀取?個?級索引的成本:

按照某個搜索條件讀取?個?級索引

根據從該?級索引得到的主鍵值進?回表操作,然后再過濾其他的搜索條件

讀取多個?級索引之后取交集成本:

按照不同的搜索條件分別讀取不同的?級索引

將從多個?級索引得到的主鍵值取交集,然后進?回表操作

雖然讀取多個?級索引?讀取?個?級索引消耗性能,但是讀取?級索引的操作是順序I/O,?回表操作是隨機I/O,所以如果只讀取?個?級索引時需要回表的記 錄數特別多,?讀取多個?級索引之后取交集的記錄數?常少,當節省的因為回表?造成的性能損耗?訪問多個?級索引帶來的性能損耗更?時,讀取多個?級索 引后取交集?只讀取?個?級索引的成本更低。

MySQL在某些特定的情況下才可能會使?到Intersection索引合并:

情況?:?級索引列是等值匹配的情況,對于聯合索引來說,在聯合索引中的每個列都必須等值匹配,不能出現只匹配部分列的情況。

??說下邊這個查詢可能?到idx_key1和idx_key_part這兩個?級索引進?Intersection索引合并的操作:

SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';

?下邊這兩個查詢就不能進?Intersection索引合并:

SELECT * FROM single_table WHERE key1 > 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';

SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a';

第?個查詢是因為對key1進?了范圍匹配,第?個查詢是因為聯合索引idx_key_part中的key_part2列并沒有出現在搜索條件中,所以這兩個查詢不能進? Intersection索引合并。

情況?:主鍵列可以是范圍匹配

??說下邊這個查詢可能?到主鍵和idx_key1進?Intersection索引合并的操作:

SELECT * FROM single_table WHERE id > 100 AND key1 = 'a';

為啥呢?憑啥呀?突然冒出這么兩個規定讓?家?臉懵逼,下邊我們慢慢品?品這?頭的?機。這話還得從InnoDB的索引結構說起,你要是記不清麻煩再回頭看 看。對于InnoDB的?級索引來說,記錄先是按照索引列進?排序,如果該?級索引是?個聯合索引,那么會按照聯合索引中的各個列依次排序。??級索引的? 戶記錄是由索引列 + 主鍵構成的,?級索引列的值相同的記錄可能會有好多條,這些索引列的值相同的記錄?是按照主鍵的值進?排序的。

所以重點來了,之所以 在?級索引列都是等值匹配的情況下才可能使?Intersection索引合并,是因為只有在這種情況下根據?級索引查詢出的結果集是按照主鍵值排序的。

so?還是沒看懂根據?級索引查詢出的結果集是按照主鍵值排序的對使?Intersection索引合并有啥好處??伙?,別忘了Intersection索引合并會把從多個? 級索引中查詢出的主鍵值求交集,如果從各個?級索引中查詢的到的結果集本身就是已經按照主鍵排好序的,那么求交集的過程就很easy啦。假設某個查詢使? Intersection索引合并的?式從idx_key1和idx_key2這兩個?級索引中獲取到的主鍵值分別是:

從idx_key1中獲取到已經排好序的主鍵值:1、3、5

從idx_key2中獲取到已經排好序的主鍵值:2、3、4

那么求交集的過程就是這樣:逐個取出這兩個結果集中最?的主鍵值,如果兩個值相等,則加?最后的交集結果中,否則丟棄當前較?的主鍵值,再取該丟棄的 主鍵值所在結果集的后?個主鍵值來?較,直到某個結果集中的主鍵值?完了,如果還是覺得不太明?那繼續往下看:

先取出這兩個結果集中較?的主鍵值做?較,因為1 < 2,所以把idx_key1的結果集的主鍵值1丟棄,取出后邊的3來?較。

因為3 > 2,所以把idx_key2的結果集的主鍵值2丟棄,取出后邊的3來?較。

因為3 = 3,所以把3加?到最后的交集結果中,繼續兩個結果集后邊的主鍵值來?較。

后邊的主鍵值也不相等,所以最后的交集結果中只包含主鍵值3。

別看我們寫的啰嗦,這個過程其實可快了,時間復雜度是O(n),但是如果從各個?級索引中查詢出的結果集并不是按照主鍵排序的話,那就要先把結果集中的主 鍵值排序完再來做上邊的那個過程,就?較耗時了。

另外,不僅是多個?級索引之間可以采?Intersection索引合并,索引合并也可以有聚簇索引參加,也就是我們上邊寫的情況?:在搜索條件中有主鍵的范圍匹配 的情況下也可以使?Intersection索引合并索引合并。為啥主鍵這就可以范圍匹配了?還是得回到應?場景?,?如看下邊這個查詢:

SELECT * FROM single_table WHERE key1 = 'a' AND id > 100;

假設這個查詢可以采?Intersection索引合并,我們理所當然的以為這個查詢會分別按照id > 100這個條件從聚簇索引中獲取?些記錄,在通過key1 = 'a'這個 條件從idx_key1?級索引中獲取?些記錄,然后再求交集,其實這樣就把問題復雜化了,沒必要從聚簇索引中獲取?次記錄。別忘了?級索引的記錄中都帶有主 鍵值的,所以可以在從idx_key1中獲取到的主鍵值上直接運?條件id > 100過濾就?了,這樣多簡單。所以涉及主鍵的搜索條件只不過是為了從別的?級索引得 到的結果集中過濾記錄罷了,是不是等值匹配不重要。

當然,上邊說的情況?和情況?只是發?Intersection索引合并的必要條件,不是充分條件。也就是說即使情況?、情況?成?,也不?定發?Intersection索引 合并,這得看優化器的?情。優化器只有在單獨根據搜索條件從某個?級索引中獲取的記錄數太多,導致回表開銷太?,?通過Intersection索引合并后需要回 表的記錄數??減少時才會使?Intersection索引合并。

Union合并

union是并集的意思,適用于不通索引的搜索條件之間使用or連接起來的情況。

情況?:?級索引列是等值匹配的情況,對于聯合索引來說,在聯合索引中的每個列都必須等值匹配,不能出現只出現匹配部分列的情況。

比如說下邊這個查詢可能?到idx_key1和idx_key_part這兩個二級索引進行Union索引合并的操作:

SELECT * FROM single_table WHERE key1 = 'a' OR ( key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c');

而下邊這兩個查詢就不能進行Union索引合并:

SELECT * FROM single_table WHERE key1 > 'a' OR (key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c');

SELECT * FROM single_table WHERE key1 = 'a' OR key_part1 = 'a';

第?個查詢是因為對key1進行了范圍匹配,第?個查詢是因為聯合索引idx_key_part中的key_part2列并沒有出現在搜索條件中,所以這兩個查詢不能進行?Union索引合并。

情況?:主鍵列可以是范圍匹配

情況三:使用Intersection索引合并的搜索條件

這種情況其實也挺好理解,就是搜索條件的某些部分使用Intersection索引合并的方式得到的主鍵集合和其他方式得到的主鍵集合取交集,比方說這個查 詢:

SELECT * FROM single_table WHERE key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c' OR (key1 = 'a' AND key3 = 'b');

優化器可能采用這樣的方式來執行這個查詢:

先按照搜索條件key1 = 'a' AND key3 = 'b'從索引idx_key1和idx_key3中使?Intersection索引合并的方式得到?個主鍵集合。

再按照搜索條件key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c'從聯合索引idx_key_part中得到另?個主鍵集合。

采用Union索引合并的方式把上述兩個主鍵集合取并集,然后進行回表操作,將結果返回給?戶。

當然,查詢條件符合了這些情況也不?定就會采用Union索引合并,也得看優化器的心情。優化器只有在單獨根據搜索條件從某個?級索引中獲取的記錄數比較少,通過Union索引合并后進行訪問的代價比全表掃描更小時才會使用Union索引合并。

Sort-Union合并

Union索引合并的使?條件太苛刻,必須保證各個?級索引列在進?等值匹配的條件下才可能被?到,??說下邊這個查詢就?法使?到Union索引合并:

SELECT * FROM single_table WHERE key1 < 'a' OR key3 > 'z'

這是因為根據key1 < 'a'從idx_key1索引中獲取的?級索引記錄的主鍵值不是排好序的,根據key3 > 'z'從idx_key3索引中獲取的?級索引記錄的主鍵值也不是 排好序的,但是key1 < 'a'和key3 > 'z'這兩個條件?特別讓我們動?,所以我們可以這樣:

先根據key1 < 'a'條件從idx_key1?級索引總獲取記錄,并按照記錄的主鍵值進?排序

再根據key3 > 'z'條件從idx_key3?級索引總獲取記錄,并按照記錄的主鍵值進?排序

因為上述的兩個?級索引主鍵值都是排好序的,剩下的操作和Union索引合并?式就?樣了。

我們把上述這種先按照?級索引記錄的主鍵值進?排序,之后按照Union索引合并?式執?的?式稱之為Sort-Union索引合并,很顯然,這種Sort-Union索引合 并?單純的Union索引合并多了?步對?級索引記錄的主鍵值排序的過程。

為啥有Sort-Union索引合并,就沒有Sort-Intersection索引合并么?是的,的確沒有Sort-Intersection索引合并這么?說, SortUnion的適?場景是單獨根據搜索條件從某個?級索引中獲取的記錄數?較少,這樣即使對這些?級索引記錄按照主鍵值進?排序的成本也不 會太? ?Intersection索引合并的適?場景是單獨根據搜索條件從某個?級索引中獲取的記錄數太多,導致回表開銷太?,合并后可以明顯降 低回表開銷,但是如果加?Sort-Intersection后,就需要為?量的?級索引記錄按照主鍵值進?排序,這個成本可能?回表查詢都?了,所以 也就沒有引?Sort-Intersection。

索引合并注意事項

聯合索引替代Intersection索引合并

SELECT * FROM single_table WHERE key1 = 'a' AND key3 = 'b';

這個查詢之所以可能使?Intersection索引合并的?式執?,還不是因為idx_key1和idx_key3是兩個單獨的B+樹索引,你要是把這兩個列搞?個聯合索引,那直 接使?這個聯合索引就把事情搞定了,何必?啥索引合并呢,就像這樣:

ALTER TABLE single_table drop index idx_key1, idx_key3, add index idx_key1_key3(key1, key3);

這樣我們把沒?的idx_key1、idx_key3都?掉,再添加?個聯合索引idx_key1_key3,使?這個聯合索引進?查詢簡直是?快?好,既不?多讀?棵B+樹,也不 ?合并結果,何樂?不為?

注意:不過??有單獨對key3列進?查詢的業務場景,這樣?不得不再把key3列的單獨索引給加上

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/214359.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/214359.shtml
英文地址,請注明出處:http://en.pswp.cn/news/214359.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

為什么同一張顯卡,深度學習的模型訓練的時候,有時候成功了,有時候失敗了

在同一張顯卡上進行深度學習模型訓練時&#xff0c;成功或失敗的結果可能受到以下因素的影響&#xff1a; 隨機性: 深度學習模型中的一些組件&#xff08;如權重初始化、數據的隨機排列等&#xff09;可能涉及到隨機性。這可能導致在每次訓練時得到不同的結果&#xff0c;有時成…

Mybatis進階知識

Mybatis的事務管理機制 在mybatis-config.xml文件中.可以進行mybatis的事務管理 <transactionManager type"JDBC"/> type的值有兩個 JDBCMANAGED JDBC事務管理器 mybatis框架自己管理事務&#xff0c;自己采用原生的JDBC代碼去管理事務 底層創建的事務管…

匯總區間算法(leetcode第228題)

題目描述&#xff1a; 給定一個 無重復元素 的 有序 整數數組 nums 。返回 恰好覆蓋數組中所有數字 的 最小有序 區間范圍列表 。也就是說&#xff0c;nums 的每個元素都恰好被某個區間范圍所覆蓋&#xff0c;并且不存在屬于某個范圍但不屬于 nums 的數字 x 。列表中的每個區…

財務機器人(RPA)會影響會計人員從業嗎?

財務機器人會對會計從業人員有影響。 不過是正面積極的影響。 它是財務人員工作的好助手好幫手。 具體展開聊聊財務RPA機器人是如何成為財務人員的好幫手。 財務機器人是在人工智能和自動化技術的基礎上建立的、以軟件機器人作為虛擬勞動力、依據預先設定的程序與現有用戶系…

活用異常處理(try-except)

介紹 簡要介紹Python的異常處理&#xff08;try-except&#xff09;。 基本語法 Try-except是Python中異常處理的基礎。 作為例子&#xff0c;我們將解釋執行除零時發生 ZeroDivisionError 的情況。 當除以零時&#xff0c;會出現以下錯誤。 print(1 / 0) # ZeroDivisionE…

藍牙配對、連接和刪除匯總

目的&#xff1a;處理PC連接藍牙設備的配對、連接和刪除操作&#xff0c;以及常見故障。 命令行配對藍牙設備并連接 要求&#xff1a;配對BLUET043藍牙&#xff0c;密碼為4444&#xff0c;然后連接該藍牙。操作步驟如下&#xff1a; Step1.下載 修復工具&#xff0c;然后安裝…

利用python編寫簡易POC腳本

POC&#xff1a;概念證明&#xff0c;即概念驗證&#xff08;英語&#xff1a;Proof of concept&#xff0c;簡稱POC&#xff09;是對某些想法的一個較短而不完整的實現&#xff0c;以證明其可行性&#xff0c;示范其原理&#xff0c;其目的是為了驗證一些概念或理論。 聲明&a…

三哥的黑科技,印度發布無線加熱服裝專利,冬季神器要來了

眾所周知風和自由在冬天是不存在的&#xff0c;冬天只剩下冰冷的像刀子一樣的風刮在你的臉上&#xff0c;哪怕穿的很厚&#xff0c;戴上全盔&#xff0c;也無法阻擋冰冷的風帶走你身體溫度&#xff0c;如果穿的特別多&#xff0c;騎車時候的舒適感和穿脫衣物的繁瑣也是一大頭疼…

【MySQL系列】Centos安裝MySQL

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

vim常用鍵位總結

1、移動光標 按鍵作用h或←光標向左移動一個字符j或↓光標向下移動一個字符k或↑光標向上移動一個字符l或→光標向右移動一個字符Ctrl f或Page Down屏幕向下移動一頁&#xff08;常用&#xff09;Ctrl b或Page Up屏幕向上移動一頁&#xff08;常用&#xff09;Ctrl d屏幕向…

Kafka使用總結

1、Kafka是何如做到高性能的&#xff1f; a、消息批處理減少網絡通信開銷&#xff0c;提升系統吞吐能力&#xff08;先攢一波&#xff0c;消息以“批”為單位進行處理&#xff09; 生產端&#xff1a;無論是同步發送還是異步發送&#xff0c;Kafka都不會立即就把這條消息發送出…

【C++】算法庫(復制操作、交換操作、變換操作)

C算法庫 文章目錄 C算法庫復制操作copy , copy_ifcopy_ncopy_backward 交換操作swapswap_rangesiter_swap 變換操作transformreplacereplace_copy replace_copy_if 算法庫提供大量用途的函數&#xff08;例如查找、排序、計數、操作&#xff09;&#xff0c;它們在元素范圍上操…

java--StringBuilder、StringBuffer、StringJoiner

1.StringBuilder ①StringBuilder代表可變字符串對象&#xff0c;相當于是一個容器&#xff0c;它里面裝的字符串是可以改變的&#xff0c;就是用來操作字符串的。 ②好處&#xff1a;StringBuilder比String更適合做字符串的修改操作&#xff0c;效率會比更高&#xff0c;代碼…

Java入門:EditPlus的安裝與配置講解

1. 前言 Java是一種面向對象的編程語言&#xff0c;廣泛應用于各種平臺和設備。在Java開發過程中&#xff0c;一個好的集成開發環境&#xff08;IDE&#xff09;是非常重要的。EditPlus是一款簡單易用的文本編輯器&#xff0c;它提供了一些方便的功能來支持Java開發。本文將介…

【開源】基于JAVA的木馬文件檢測系統

項目編號&#xff1a; S 041 &#xff0c;文末獲取源碼。 \color{red}{項目編號&#xff1a;S041&#xff0c;文末獲取源碼。} 項目編號&#xff1a;S041&#xff0c;文末獲取源碼。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 數據中心模塊2.2 木馬分類模塊2.3 木…

Leo贈書活動-13期 【以企業架構為中心的SABOE數字化轉型五環法】文末送書

Leo贈書活動-13期 【以企業架構為中心的SABOE數字化轉型五環法】文末送書 ?作者簡介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;熱愛Java后端開發者&#xff0c;一個想要與大家共同進步的男人&#x1f609;&#x1f609; &#x1f34e;個人主頁&#xff1a;Leo的博客…

記錄 | xshell輸出錯亂解決

輸出錯亂問題&#xff1a; 解決方法&#xff1a;

VS Code使用 CMake 或 Makefile管理C++多文件編譯

VS Code使用 CMake 或 Makefile管理C多文件編譯 一、Cmake方式1、文件結構2、構建項目 二、Makefile方式1、文件結構2、Makefile3、構建項目 三、附件示例中使用到的文件及代碼 使用 CMake 或 Makefile 是更加標準和靈活的方法來管理多文件編譯。以下是一個簡單的示例&#xff…

80個常用shell命令及簡單用法

Shell命令是Linux和Unix系統中的基礎&#xff0c;用于完成各種操作&#xff0c;如文件管理、程序執行、文本處理等。下面列舉一些常用的Shell命令&#xff0c;并詳細解釋它們的功能及應用場景&#xff1a; ls - 列出目錄內容 功能&#xff1a;列出指定目錄中的文件和目錄。應用…