您好,登錄后才能下訂單哦!
這篇文章主要介紹了MySQL索引提高查詢效率的方法,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。
MySQL的索引本質上是一種數據結構
讓我們先來了解一下計算機的數據加載。
先說一下磁盤IO,磁盤讀取數據靠的是機械運動,每一次讀取數據需要尋道、尋點、拷貝到內存三步操作。
尋道時間是磁臂移動到指定磁道所需要的時間,一般在5ms以下;
尋點是從磁道中找到數據存在的那個點,平均時間是半圈時間,如果是一個7200轉/min的磁盤,尋點時間平均是600000/7200/2=4.17ms;
拷貝到內存的時間很快,和前面兩個時間比起來可以忽略不計,所以一次IO的時間平均是在9ms左右。聽起來很快,但數據庫百萬級別的數據過一遍就達到了9000s,顯然就是災難級別的了。
考慮到磁盤IO是非常高昂的操作,計算機操作系統做了預讀的優化,當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩沖區內,因為當計算機訪問一個地址的數據的時候,與其相鄰的數據也會很快被訪問到。
每一次IO讀取的數據我們稱之為一頁(page),具體一頁有多大數據跟操作系統有關,一般為4k或8k,也就是我們讀取一頁內的數據時候,實際上才發生了一次IO。
(突然想到個我剛畢業被問過的問題,在64位的操作系統中,Java中的int類型占幾個字節?最大是多少?為什么?)
那我們想要優化數據庫查詢,就要盡量減少磁盤的IO操作,所以就出現了索引。
MySQL
官方對索引的定義為:索引(Index)是幫助MySQL
高效獲取數據的數據結構。
MySQL
中常用的索引在物理上分兩類,B-樹索引和哈希索引。
本次主要講BTree
索引。
BTree
又叫多路平衡查找樹,一顆m叉的BTree特性如下:
這是一個3叉(只是舉例,真實會有很多叉)的BTree結構圖,每一個方框塊我們稱之為一個磁盤塊或者叫做一個block塊,這是操作系統一次IO往內存中讀的內容,一個塊對應四個扇區,紫色代表的是磁盤塊中的數據key,黃色代表的是數據data,藍色代表的是指針p,指向下一個磁盤塊的位置。
來模擬下查找key為29的data的過程:
1、根據根結點指針讀取文件目錄的根磁盤塊1。【磁盤IO操作1次】
2、磁盤塊1存儲17,35和三個指針數據。我們發現17<29<35,因此我們找到指針p2。
3、根據p2指針,我們定位并讀取磁盤塊3。【磁盤IO操作2次】
4、磁盤塊3存儲26,30和三個指針數據。我們發現26<29<30,因此我們找到指針p2。
5、根據p2指針,我們定位并讀取磁盤塊8。【磁盤IO操作3次】
6、磁盤塊8中存儲28,29。我們找到29,獲取29所對應的數據data。
由此可見,BTree索引使每次磁盤I/O取到內存的數據都發揮了作用,從而提高了查詢效率。
但是有沒有什么可優化的地方呢?
我們從圖上可以看到,每個節點中不僅包含數據的key值,還有data值。而每一個頁的存儲空間是有限的,如果data數據較大時將會導致每個節點(即一個頁)能存儲的key的數量很小,當存儲的數據量很大時同樣會導致B-Tree的深度較大,增大查詢時的磁盤I/O次數,進而影響查詢效率。
B+Tree
是在B-Tree
基礎上的一種優化,使其更適合實現外存儲索引結構。在B+Tree中,所有數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲key值信息,這樣可以大大加大每個節點存儲的key值數量,降低B+Tree的高度。
B+Tree相對于B-Tree有幾點不同:
非葉子節點只存儲鍵值信息, 數據記錄都存放在葉子節點中, 將上一節中的B-Tree優化,由于B+Tree的非葉子節點只存儲鍵值信息,所以B+Tree的高度可以被壓縮到特別的低。
具體的數據如下:
InnoDB存儲引擎中頁的大小為16KB,一般表的主鍵類型為INT(占用4個字節)或BIGINT(占用8個字節),指針類型也一般為4或8個字節,也就是說一個頁(B+Tree中的一個節點)中大概存儲16KB/(8B+8B)=1K個鍵值(因為是估值,為方便計算,這里的K取值為〖10〗^3)。
也就是說一個深度為3的B+Tree索引可以維護10^3 10^3 10^3 = 10億 條記錄。(這種計算方式存在誤差,而且沒有計算葉子節點,如果計算葉子節點其實是深度為4了)
我們只需要進行三次的IO操作就可以從10億條數據中找到我們想要的數據,比起最開始的百萬數據9000秒不知道好了多少個華萊士了。
而且在B+Tree上通常有兩個頭指針,一個指向根節點,另一個指向關鍵字最小的葉子節點,而且所有葉子節點(即數據節點)之間是一種鏈式環結構。所以我們除了可以對B+Tree進行主鍵的范圍查找和分頁查找,還可以從根節點開始,進行隨機查找。
數據庫中的B+Tree索引可以分為聚集索引(clustered index)和輔助索引(secondary index)。
上面的B+Tree示例圖在數據庫中的實現即為聚集索引,聚集索引的B+Tree中的葉子節點存放的是整張表的行記錄數據,輔助索引與聚集索引的區別在于輔助索引的葉子節點并不包含行記錄的全部數據,而是存儲相應行數據的聚集索引鍵,即主鍵。
當通過輔助索引來查詢數據時,InnoDB存儲引擎會遍歷輔助索引找到主鍵,然后再通過主鍵在聚集索引中找到完整的行記錄數據。
不過,雖然索引可以加快查詢速度,提高 MySQL 的處理性能,但是過多地使用索引也會造成以下弊端:
注意:索引可以在一些情況下加速查詢,但是在某些情況下,會降低效率。
索引只是提高效率的一個因素,因此在建立索引的時候應該遵循以下原則:
現在大家知道索引為啥能這么快了吧,其實就是一句話,通過索引的結構最大化的減少數據庫的IO次數,畢竟,一次IO的時間真的是太久了。。。
感謝你能夠認真閱讀完這篇文章,希望小編分享MySQL索引提高查詢效率的方法內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。