提及Mysql就離不開SQL優化,提及優化就離不開索引,那麼什麼是索引?爲何加了索引就能夠快?那接下來咱們就一塊兒來探討一下索引相關的知識!sql
【對這塊數據結構瞭解的同窗建議跳過本節】
提及二叉樹,咱們都知道每一個結點最多隻能有兩個子結點,例如:
能夠發現二叉樹頗有規律,左子結點小於當前結點,右子結點大於當前結點。那這樣不是查詢起來很方便呢?二叉樹的性質決定了它的時間複雜度爲 Olog(n),固然,二叉樹的時間複雜度與它的插入順序有着,若是按升序或降序的方式插入數據,那麼它的二叉樹的高度h就與結點個數相等了,此時複雜度就提升到了O(n)。數據庫
假如,數據庫使用二叉樹來作索引,此時須要插入1000條數據,咱們來計算一下這樹的高度。(深度爲k的二叉樹最少有k個結點,最多有2^k-1個結點)數據結構
2^10-1 ≈ 1000 此時樹的高度約爲10 最差的狀況,樹的高度爲1000
樹的高度決定了查詢的效率,而二叉樹又會存在高度10~1000這麼大的差距,很明顯它已經不適合作咱們的索引了!ide
前面把問題擺出來了,二叉樹的高度很不穩定,那咱們能不能把高度穩定一下呢?這就是平衡樹,它會根據插入的狀況,動態的調整二叉樹的高度(左右子樹的高度最多差1),好比:咱們插入從10,9,8,,,1
看,我沒有騙你吧,它會根據插入的狀況調整樹的高度,具體怎麼調整的,我只簡單說明一下吧,畢竟不是本文的重點。性能
平衡樹的調整分四種狀況:優化
LL、LR、RL、RR
這種狀況很好理解操作系統
這種狀況就是,先將5與6結點左旋轉,而後轉成了LL型,再右旋轉。
好了,另外兩種就不說了,和這兩種的旋轉方式正好相反而已。3d
咳咳,回到正題,如今好了,平衡樹足以保證了樹的平衡,那麼使用它來作索引有沒有 問題呢?
假如咱們有100000 條記錄,那麼根據二叉樹的性質,樹的高度最低約爲2^16,也就是查找一個元素須要查找16次,有同窗可能說,嗯,查詢16次我能夠接受了,那麼假如插入或刪除數據呢?AVL樹的最大缺點就是插入結點時,樹須要頻繁的旋轉調整結點,因此平衡樹也不太適合作索引。指針
前面說了平衡樹對二叉樹的要求,左右子樹的高度最多差1,插入數據稍有不慎就會形成平衡樹的轉換操做,而轉換又是很是耗時的一件事情。
而紅黑樹的出現就是爲了不平衡樹的頻繁轉換結點操做。紅黑樹 並不追求 徹底平衡 它只要求部分結點達到平衡,下降了對旋轉的要求,從而提升了性能。先看下紅黑樹的定義吧!code
* 每一個結點要麼是紅的要麼是黑的。 * 根結點是黑的。 * 每一個葉結點(葉結點即指樹尾端NIL指針或NULL結點)都是黑的。 * 若是一個結點是紅的,那麼它的兩個兒子都是黑的。 * 對於任意結點而言,其到葉結點樹尾端NIL指針的每條路徑都包含相同數目的黑結點。
插入或刪除元素時,也是須要維護紅黑樹結構的,之因此索引也不使用紅黑樹主要是二叉樹保存大量結點的時候,會致使樹的高度不斷增長。好比1億個節點,樹的高度就會達到27層左右,而通常索引又是保存到磁盤中的,若是每次查詢都須要一次IO的話,那也就是須要27次IO操做,而每次IO操做都是很是耗時的。
平衡樹、紅黑樹都是二叉樹,當二叉樹保存大量元素的時候會致使樹的高度不斷增高,那可不可使用多叉樹呢?
先來看下B樹的定義:
一、B樹的組成 關鍵字(能夠理解爲數據) 指向孩子節點的指針
二、B樹的性質: * 若根結點不是終端結點,則至少有2棵子樹 * 除根節點之外的全部非葉結點至少有 M/2 棵子樹,至多有 M 個子樹(關鍵字數爲子樹減一) * 全部的葉子結點都位於同一層
B+樹與B樹的區別主要在於:
* 節點的子樹數和關鍵字數相同(B 樹是關鍵字數比子樹數少一) * 節點的關鍵字表示的是子樹中的最大數,在子樹中一樣含有這個數據 * 葉子節點包含了所有數據,同時符合左小右大的順序
B+樹相比B樹的優勢再於:層級更低,葉子結點造成鏈表,範圍查詢方便;
索引文件通常以文件的形式存在磁盤上面,索引檢索操做須要磁盤的IO,可是磁盤順序讀取的效率很高,因此在讀取的時候,磁盤每每不是按需讀取,並且每次都會預讀,即便只須要一個字節,磁盤也會從這個位置開始,順序向後讀取必定長度的數據放入內存。因爲磁盤順序讀取的效率很高,所以對於具備局部性的程序來講,預讀能夠提升IO效率。預讀的長度通常爲頁的整數倍(頁是計算機管理存儲器的邏輯塊,操做系統每每將主存和磁盤存儲區分割爲連續的大小相等的塊,每一個存儲塊稱爲一頁,大小一般是4K)主存和磁盤以頁爲單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,而後異常返回,程序繼續運行
Innodb中使用是B+樹做爲索引,好比下圖中的主索引:
葉子結點包含了因此的結點,除了葉子結點以外,其它結點不包含值,而葉子結點包含具體的值
二級索引
Innodb中的二級索引,也是一棵B+樹,只是它的葉子結點指向的是主索引中的主鍵值,而後再去主索引中查找具體的值;
MyISAM引擎使用B+樹做索引時,結構與Innodb大體相同,只是它葉子結點存放的不是具體的記錄值,而是記錄的地址。
二級索引
一級索引中,MyISAM的索引文件僅僅保存數據記錄的地址,而二級索引在結構上沒有任何區別,二級索引也是直接指向記錄的地址。