您好,登錄后才能下訂單哦!
本文主要給大家簡單講講MySQL中的索引有哪些類型或者種類,相關專業術語大家可以上網查查或者找一些相關書籍補充一下,這里就不涉獵了,我們就直奔主題吧,希望MySQL中的索引有哪些類型或者種類這篇文章可以給大家帶來一些實際幫助。
什么是索引
索引是一種數據結構,其作用就是用來提高數據查詢效率。比較常用的比喻就是將其類比為書籍的目錄。通過目錄可以精確的找到某一章節的內容所在頁。
在數據量較小的時候使用索引其實也沒有什么意義,即使沒有索引需要一條一條遍歷數據對于計算機來說也并不需要太多時間。而一旦數據量較大,要保證我們能正常的對外提供服務,保證用戶使用體驗那么索引就是必要的了。
索引類型
索引是一種數據結構,為了應對不同的場景會有多種實現。在MySQL中主要就是Hash索引和B+Tree。
Hash索引
hash相信大家應該都很熟悉,hash是一種key-value形式的數據結構。實現一般是數組+鏈表的結構,通過hash函數計算出key在數組中的位置,然后如果出現hash沖突就通過鏈表來解決(拉鏈法)。當然還有其他的解決hash沖突的方法。hash這種數據結構是很常用的,比如我們系統使用HashMap來構建熱點數據緩存,存取效率很好。
hash結構存數據首先通過計算key的hash值來確定其在數組中的位置,如果有沖突就在該數組位置建一個鏈表。這樣很明顯有幾個問題:
即使是具有相同特征的key計算出來的位置可能相隔很遠,連續查詢效率低下。即不支持范圍查詢。
hash索引存儲的事計算得到的hash值和行指針,而不存儲具體的行值,所以通過hash索引查詢數據需要進行兩次查詢(首先查詢行的位置,然后找到具體的數據)
hash索引查詢數據的前提就是計算hash值,也就是要求key為一個能準確指向一條數據的key,所以對于like等一類的匹配查詢是不支持的。
所以我們可以知道的是hash索引適用于快速選取某一行的數據。
B+Tree結構
從名字上看這明顯是一種樹結構,在大學期間數據結構的課本上樹結構是必講的。樹結構是一種特別重要的數據結構,在很多地方都會使用到。
上面我們說到hash索引無法進行范圍查詢,在樹結構中也有一種方便進行有序查詢的結構--二叉搜索樹。二叉搜索樹的結構中要求父節點的值大于左孩子節點并且小于右孩子節點,如下圖:
上圖中二叉樹的查詢的時間復雜度為O(log(n)),當然要保證O(log(n))的時間復雜度就需要保證二叉樹時刻保持平衡。
而在MySQL索引中雖然也使用了樹結構,但是并不是使用的二叉樹。因為在數據庫中數據最終都是存放在磁盤上的,而如果樹的節點過多的話,那么在節點之間轉移會花費較多的時間。在MySQL的實現中選擇將更多內容放在同一個節點,對同一個節點的操作轉入在內存中完成,減少在外存中節點之間轉移的次數,以達到提高效率的目的。這就是B+Tree,在B+Tree的實現中一個三層的樹結構就基本上可以滿足我們幾乎所有的需求了。
相關推薦:《mysql數據庫知識學習》
B-Tree
要了解B+Tree首先就得了解B-Tree,B-Tree是一種平衡樹,這里的B指的是Balance而不是Binary,更確切的說B-Tree是一種多路平衡搜索樹。
多路平衡搜索樹如下圖:
這是一種2-3樹,意思就是每個節點存有兩個值,同時每個節點分支數為3,從上圖中可以看出來著中結構很適合查詢數據。每個節點的左子樹的值都是小于當前節點中最小的值,中間的子樹的值全都是在當前節點兩個值的中間,而右子樹的值全都大于當前節點的最大值。
比如我們要查找24這個值:
(1)首先從根節點判斷24在根節點(15,25)之間,所以左右子樹排除,從中間查找。
(2)然后找到中間子樹的根節點(18,22),比較發現24大于該節點最大值,排除左子樹和中間子樹。
(3)找到右子樹,判斷節點大值剛好等于24,查詢結束。
基于上面的流程可以總結B樹的搜索:
(1)從根結點開始,對結點內的關鍵字(有序)序列進行二分查找。
(2)如果命中則結束,否則進入查詢關鍵字所屬范圍的子結點;
(3)重復上面的流程,直到所對應的子節點為空,或已經是葉子結點;
可以看出其搜索性能相當于在關鍵字集合內做一次二分查找。從這里看來好像B-Tree沒有什么問題,但是需要注意到的是在B-Tree中每一個節點都是存儲索引關鍵字以及其代表的具體行數據。而在MySQL中數據庫加載數據是以頁為單位加載,每一頁的大小是固定的(默認16k)。如果每一個節點都存儲所有的值,那么一頁中能存下的節點就會很少,一次查詢可能就會進行多次從內存中去加載數據,導致性能降低。
B+Tree
B+Tree是對B-Tree的一個變種,讓其更加適應于進行外部存儲文件索引。
兩者之前最大的不同就在于B-Tree的每個節點都存儲所有的數據,而B+Tree需要存儲的數據都在葉子節點上,并且增加了順序訪問指針,每個葉子節點都有指向下一個相鄰的葉子節點的地址。這樣的結構保證了在一個內存頁中可以存下更多的索引節點,并且更加適合進行范圍查詢。
索引
因為存儲引擎負責實現索引,所以接下來討論索引都是基于MySQL的InnoDB引擎。
聚簇索引
聚簇的意思是表示數據行和相鄰的鍵值聚簇的存儲在一起。一些數據庫允許選擇具體的某一個索引作為聚簇索引,而在InnoDB的實現中直接將主鍵索引指定為聚簇索引。如果沒有定義主鍵,InnoDB 會選擇一個唯一的非空索引來代替主鍵索引。如果同樣沒有定義這樣的索引,InnoDB會隱式定義一個主鍵來作為聚簇索引(row_id)。
聚簇索引實例如圖:
非聚簇索引索引
在InnoDB中除主鍵索引外其他都是非聚簇索引,所以也叫非主鍵索引。非主鍵索引的葉節點并不是存儲一行的值,而是存儲具體行的主鍵值。不滿足聚簇的定義。
非聚簇索引實例如圖:
聚簇索引和非聚簇索引在查詢時的差異
由上面的兩種索引實例圖就可以看出來,在查詢時如果是通過主鍵索引查詢的話直接查詢到數據行然后返回。但是如果是通過非主鍵索引查詢的話首先需要通過該索引確定主鍵,然后通過得到的主鍵從主鍵索引中查到具體行的數據,后面的通過得到的主鍵從主鍵索引中獲取數據的過程被稱為回表。
回表的過程使得通過普通索引查詢較主鍵索引查詢多了一步,在很多情況下效率相對較低。所以在我們的查詢過程中如果能夠僅通過主鍵確定數據那最好就是直接使用主鍵進行查詢。
覆蓋索引
上面介紹了通過非主鍵查詢會有一個回表的過程,但是需要注意的是并不是每一個查詢都存在回表這一步,對于一個普通索引來說其葉節點存儲的是主鍵的值,那么假設我現在需要的數據也僅僅就是主鍵的值呢?通過普通索引取到主鍵的值后就并不需要再到主鍵索引中查,那么也就不存在回表這一過程了。
上面例子中該非主鍵索引已經存在了我們所需要的值,所以該索引也被稱為覆蓋索引。覆蓋索引并不是一個固定的結構,可以使單索引(一個字段的索引),也可以使復合索引,凡是能夠直接提供查詢結果而不需要進行回表過程的都可以被稱為覆蓋索引。
很多時候我們不可能僅僅通過主鍵來確定數據,使用普通索引可能會導致低效,所以覆蓋索引在日常開發過程中也是一個很常用的性能優化的手段。
當然覆蓋索引頁并不都是好的,比如我現在建立了一個索引index(a,b)。由a,b兩個字段來建立索引,好處已經說過了就是查詢ab字段時不會回表,但是如果僅僅通過b字段來查詢就無法走這個索引了。建立的索引的索引項是按照索引定義里面出現的字段順序排序的。
最左前綴原則
假設現在存在索引index(a,b),那么如果通過a和b來查詢能夠應用該索引,單獨使用a來查詢也能應用到該索引,但是如果單獨使用b來查詢則無法應用到該索引。這就是最左前綴原則,在匹配索引時回匹配索引最左邊的n個字段,能匹配上就可以應用該索引。
由于最左前綴原則的存在也就要求我們在建立索引時可能需要考慮更多的事情。
首先需要清楚的事索引是一種數據結構,建立索引時需要消耗存儲空間的,所以索引并不是建立的越多越好,而是應該根據需求盡可能的減少索引的數量。
而最左前綴原則的存在就使得一個聯合索引可以被當成多個索引來使用,當然前提是設計好索引中字段的順序(實際上最左前綴原則也并不是僅僅適用于聯合索引,對于字符串索引也使用,字符串索引中最左n個字符相當于聯合索引中的最左n個字段)。
比如index(a,b),有了這個索引后我們就不需要單獨為a建立索引,所以在設計聯合索引時一般將使用頻率較高的字段放在前面。
然后是將區分度較高的字段靠前,區分度就是字段中值的重復率,重復率越低區分度越高。比如性別就不適合作為索引,區分度越高的字段經過一次篩選能過濾掉更多的行。
然后還需要考慮的是字段的大小,由于索引也需要占據空間所以一般選用較小的字段。
MySQL中的索引有哪些類型或者種類就先給大家講到這里,對于其它相關問題大家想要了解的可以持續關注我們的行業資訊。我們的板塊內容每天都會捕捉一些行業新聞及專業知識分享給大家的。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。