欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql執(zhí)行原理之索引合并步驟詳解

 更新時間:2022年12月20日 11:12:00   作者:Victor_An  
這篇文章主要介紹了Mysql執(zhí)行原理之索引合并詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

Mysql執(zhí)行原理之索引合并詳解

我們前邊說過MySQL在一般情況下執(zhí)行一個查詢時最多只會用到單個二級索引,但存在有特殊情況,在這些特殊情況下也可能在一個查詢中使用到多個二級索引,MySQL中這種使用到多個索引來完成一次查詢的執(zhí)行方法稱之為:索引合并/index merge,在前面的成本計算中我們說到過這個概念:“我們需要分別分析單獨(dú)使用這些索引執(zhí)行查詢的成本,最后還要分析是否可能使用到索引合并”。其實(shí)optimizer trace輸出的文本中就有這個片段:

在這里插入圖片描述

具體的索引合并算法有下邊三種。

Intersection合并

Intersection翻譯過來的意思是交集。這里是說某個查詢可以使用多個二級索引,將從多個二級索引中查詢到的結(jié)果取交集,比方說下邊這個查詢:

SELECT * FROM order_exp WHERE order_no = 'a' AND expire_time = 'b';

假設(shè)這個查詢使用Intersection合并的方式執(zhí)行的話,那這個過程就是這樣的:從idx_order_no二級索引對應(yīng)的B+樹中取出order_no= 'a’的相關(guān)記錄。從idx_insert_time二級索引對應(yīng)的B+樹中取出insert_time= 'b’的相關(guān)記錄。二級索引的記錄都是由索引列 + 主鍵構(gòu)成的,所以我們可以計算出這兩個結(jié)果集中id值的交集。
按照上一步生成的id值列表進(jìn)行回表操作,也就是從聚簇索引中把指定id值的完整用戶記錄取出來,返回給用戶。為啥不直接使用idx_order_no或者idx_insert_time只根據(jù)某個搜索條件去讀取一個二級索引,然后回表后再過濾另外一個搜索條件呢?這里要分析一下兩種查詢執(zhí)行方式之間需要的成本代價。
只讀取一個二級索引的成本:
按照某個搜索條件讀取一個二級索引,根據(jù)從該二級索引得到的主鍵值進(jìn)行回表操作,然后再過濾其他的搜索條件讀取多個二級索引之后取交集成本:
按照不同的搜索條件分別讀取不同的二級索引,將從多個二級索引得到的主鍵值取交集,然后進(jìn)行回表操作。雖然讀取多個二級索引比讀取一個二級索引消耗性能,但是大部分情況下讀取二級索引的操作是順序I/O,而回表操作是隨機(jī)I/O,所以如果只讀取一個二級索引時需要回表的記錄數(shù)特別多,而讀取多個二級索引之后取交集的記錄數(shù)非常少,當(dāng)節(jié)省的因?yàn)榛乇矶斐傻男阅軗p耗比訪問多個二級索引帶來的性能損耗更高時,讀取多個二級索引后取交集比只讀取一個二級索引的成本更低。
MySQL在某些特定的情況下才可能會使用到Intersection索引合并,哪些情況呢?

情況一:等值匹配

二級索引列是等值匹配的情況,對于聯(lián)合索引來說,在聯(lián)合索引中的每個列都必須等值匹配,不能出現(xiàn)只匹配部分列的情況。而下邊這兩個查詢就不能進(jìn)行Intersection索引合并:

SELECT * FROM order_exp WHERE order_no> 'a' AND insert_time = 'a' AND
order_status = 'b' AND expire_time = 'c';
SELECT * FROM order_exp WHERE order_no = 'a' AND insert_time = 'a';

第一個查詢是因?yàn)閷rder_no進(jìn)行了范圍匹配,第二個查詢是因?yàn)槁?lián)合索引u_idx_day_status中的order_status和expire_time列并沒有出現(xiàn)在搜索條件中,所以這兩個查詢不能進(jìn)行Intersection索引合并。

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

比方說下邊這個查詢可能用到主鍵和u_idx_day_status(insert_time, order_status,expire_time)進(jìn)行Intersection索引合并的操作:

SELECT * FROM order_exp WHERE id > 100 AND insert_time = 'a';

對于InnoDB的二級索引來說,記錄先是按照索引列進(jìn)行排序,如果該二級索引是一個聯(lián)合索引,那么會按照聯(lián)合索引中的各個列依次排序。而二級索引的用戶記錄是由索引列 + 主鍵構(gòu)成的,二級索引列的值相同的記錄可能會有好多條,這些索引列的值相同的記錄又是按照主鍵的值進(jìn)行排序的。

所以重點(diǎn)來了,之所以在二級索引列都是等值匹配的情況下才可能使用Intersection索引合并,是因?yàn)橹挥性谶@種情況下根據(jù)二級索引查詢出的結(jié)果集是按照主鍵值排序的。

Intersection索引合并會把從多個二級索引中查詢出的主鍵值求交集,如果從各個二級索引中查詢的到的結(jié)果集本身就是已經(jīng)按照主鍵排好序的,那么求交集的過程就很容易。

假設(shè)某個查詢使用Intersection索引合并的方式從idx_order_no和idx_expire_time這兩個二級索引中獲取到的主鍵值分別是:

從idx_order_no中獲取到已經(jīng)排好序的主鍵值:1、3、5

從idx_expire_time中獲取到已經(jīng)排好序的主鍵值:2、3、4

那么求交集的過程就是這樣:逐個取出這兩個結(jié)果集中最小的主鍵值,如果兩個值相等,則加入最后的交集結(jié)果中,否則丟棄當(dāng)前較小的主鍵值,再取該丟棄的主鍵值所在結(jié)果集的后一個主鍵值來比較,直到某個結(jié)果集中的主鍵值用完了,時間復(fù)雜度是O(n)。(這個求交集思路可以學(xué)習(xí)下)

但是如果從各個二級索引中查詢出的結(jié)果集并不是按照主鍵排序的話,那就要先把結(jié)果集中的主鍵值排序完再來做上邊的那個過程,就比較耗時了。

按照有序的主鍵值去回表取記錄有個專有名詞,叫:Rowid Ordered Retrieval,簡稱ROR。

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

SELECT * FROM order_exp WHERE id > 100 AND order_no = 'a';

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

當(dāng)然,上邊說的情況一和情況二只是發(fā)生Intersection索引合并的必要條件,不是充分條件。也就是說即使情況一、情況二成立,也不一定發(fā)生Intersection索引合并,這得看優(yōu)化器的心情。優(yōu)化器只有在單獨(dú)根據(jù)搜索條件從某個二級索引中獲取的記錄數(shù)太多,導(dǎo)致回表開銷太大,而通過Intersection索引合并后需要回表的記錄數(shù)大大減少時才會使用Intersection索引合并。

Union合并(并集 :  合并后可能 在 一頁 一起找出來了 同樣找的時候也可能去重,說白了減少io次數(shù))

我們在寫查詢語句時經(jīng)常想把既符合某個搜索條件的記錄取出來,也把符合另外的某個搜索條件的記錄取出來,我們說這些不同的搜索條件之間是OR關(guān)系。有時候OR關(guān)系的不同搜索條件會使用到不同的索引,比方說這樣:

SELECT * FROM order_exp WHERE order_no = 'a' OR expire_time = 'b'

Intersection是交集的意思,這適用于使用不同索引的搜索條件之間使用AND連接起來的情況;Union是并集的意思,適用于使用不同索引的搜索條件之間使用OR連接起來的情況。與Intersection索引合并類似,MySQL在某些特定的情況下才可能會使用到Union索引合并:

情況一:等值匹配
分析同Intersection合并

情況二:主鍵列可以是范圍匹配
分析同Intersection合并

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

SELECT * FROM order_exp WHERE insert_time = 'a' AND order_status = 'b' AND expire_time = 'c' OR (order_no = 'a' AND expire_time = 'b');

優(yōu)化器可能采用這樣的方式來執(zhí)行這個查詢:

先按照搜索條件order_no = 'a' AND expire_time = 'b'從索引idx_order_no和idx_expire_time中使用Intersection索引合并的方式得到一個主鍵集合。

再按照搜索條件 insert_time = 'a' AND order_status = 'b' AND expire_time = 'c'從聯(lián)合索引u_idx_day_status中得到另一個主鍵集合。

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

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

Sort-Union合并

Union索引合并的使用條件太苛刻,必須保證各個二級索引列在進(jìn)行等值匹配的條件下才可能被用到,比方說下邊這個查詢就無法使用到Union索引合并:

SELECT * FROM order_exp WHERE order_no< 'a' OR expire_time> 'z'

這是因?yàn)楦鶕?jù)order_no< 'a'從idx_order_no索引中獲取的二級索引記錄的主鍵值不是排好序的,根據(jù)expire_time> 'z'從idx_expire_time索引中獲取的二級索引記錄的主鍵值也不是排好序的,但是order_no< 'a'和expire_time> 'z''這兩個條件又特別讓我們動心,所以我們可以這樣:

先根據(jù)order_no< 'a'條件從idx_order_no二級索引中獲取記錄,并按照記錄的主鍵值進(jìn)行排序

再根據(jù)expire_time> 'z'條件從idx_expire_time二級索引中獲取記錄,并按照記錄的主鍵值進(jìn)行排序

因?yàn)樯鲜龅膬蓚€二級索引主鍵值都是排好序的,剩下的操作和Union索引合并方式就一樣了。

上述這種先按照二級索引記錄的主鍵值進(jìn)行排序,之后按照Union索引合并方式執(zhí)行的方式稱之為Sort-Union索引合并,很顯然,這種Sort-Union索引合并比單純的Union索引合并多了一步對二級索引記錄的主鍵值排序的過程。

聯(lián)合索引替代Intersection索引合并

SELECT * FROM order_exp WHERE order_no= 'a' And expire_time= 'z';

這個查詢之所以可能使用Intersection索引合并的方式執(zhí)行,還不是因?yàn)閕dx_order_no和idx_expire_time是兩個單獨(dú)的B+樹索引,要是把這兩個列搞一個聯(lián)合索引,那直接使用這個聯(lián)合索引就把事情搞定了,何必用啥索引合并呢,就像這樣:

ALTER TABLE order_exp drop index idx_order_no, idx_expire_time,

add index idx_order_no_expire_time(order_no, expire_time);

這樣我們把idx_order_no, idx_expire_time都干掉,再添加一個聯(lián)合索引idx_order_no_expire_time,使用這個聯(lián)合索引進(jìn)行查詢簡直是又快又好,既不用多讀一棵B+樹,也不用合并結(jié)果。

到此這篇關(guān)于Mysql執(zhí)行原理之索引合并詳解的文章就介紹到這了,更多相關(guān)Mysql索引合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談MySQL存儲引擎選擇 InnoDB與MyISAM的優(yōu)缺點(diǎn)分析

    淺談MySQL存儲引擎選擇 InnoDB與MyISAM的優(yōu)缺點(diǎn)分析

    MyISAM 是MySQL中默認(rèn)的存儲引擎,一般來說不是有太多人關(guān)心這個東西。決定使用什么樣的存儲引擎是一個很tricky的事情,但是還是值我們?nèi)パ芯恳幌拢@里的文章只考慮 MyISAM 和InnoDB這兩個,因?yàn)檫@兩個是最常見的
    2013-06-06
  • MySQL請求處理全流程之如何從SQL語句到數(shù)據(jù)返回

    MySQL請求處理全流程之如何從SQL語句到數(shù)據(jù)返回

    這篇文章主要介紹了MySQL請求處理全流程之如何從SQL語句到數(shù)據(jù)返回,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-03-03
  • MySQL亂碼問題終極指南

    MySQL亂碼問題終極指南

    為了讓大家盡量在工作中少受或者不受亂碼的困擾,這篇文章主要為大家分享了MySQL亂碼問題終極指南,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 淺談Mysql?tinyint(1)與tinyint(4)的區(qū)別

    淺談Mysql?tinyint(1)與tinyint(4)的區(qū)別

    本文主要介紹了淺談Mysql?tinyint(1)與tinyint(4)的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • MySQL數(shù)據(jù)庫如何查看表占用空間大小

    MySQL數(shù)據(jù)庫如何查看表占用空間大小

    由于數(shù)據(jù)太大了,所以MYSQL需要瘦身,那前提就是需要知道每個表占用的空間大小,這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫如何查看表占用空間大小的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • MySQL可以使用斜線來當(dāng)字段的名字

    MySQL可以使用斜線來當(dāng)字段的名字

    無意中發(fā)現(xiàn)MySQL可以使用斜線來當(dāng)字段的名字,下面有個示例,需要的朋友可以參考下
    2014-03-03
  • MySQL?中這么多索引該怎么選擇

    MySQL?中這么多索引該怎么選擇

    這篇文章主要介紹了MySQL?中這么多索引該怎么選擇,索引的本質(zhì)是存儲引擎用于快速查詢記錄的一種數(shù)據(jù)結(jié)構(gòu)。特別是數(shù)據(jù)表中數(shù)據(jù)特別多的時候,索引對于數(shù)據(jù)庫的性能就愈發(fā)重要,下文詳細(xì)相關(guān)內(nèi)容介紹,需要的小伙伴可以參考一下
    2022-09-09
  • mysql數(shù)據(jù)庫中字符集亂碼問題原因及解決

    mysql數(shù)據(jù)庫中字符集亂碼問題原因及解決

    這篇文章主要介紹了mysql數(shù)據(jù)庫中字符集亂碼問題原因及解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • MySQL8.0版本如何正確的使用窗口函數(shù)詳解

    MySQL8.0版本如何正確的使用窗口函數(shù)詳解

    MySQL?8.0引入的窗口函數(shù),增強(qiáng)了數(shù)據(jù)分析能力,窗口函數(shù)允許對數(shù)據(jù)集(窗口)進(jìn)行操作,與GROUPBY類似,但每個查詢行生成獨(dú)立結(jié)果,包括聚合函數(shù)如SUM、AVG,專用窗口函數(shù)如ROW_NUMBER等,窗口函數(shù)應(yīng)用于數(shù)據(jù)分組、排序、排名,并支持復(fù)雜分析場景,需要的朋友可以參考下
    2024-11-11
  • MySQL中執(zhí)行計劃explain命令示例詳解

    MySQL中執(zhí)行計劃explain命令示例詳解

    這篇文章主要給大家介紹了關(guān)于MySQL中執(zhí)行計劃explain命令的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用explain命令具有一定的參考學(xué)習(xí)價值,需要的朋友們下面說來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05

最新評論