深入解析MySQL索引原理

2021-10-07 05:42:21 字數 2982 閱讀 7191

一. 什麼是索引、為什麼要建立索引?

關於索引的理解,個人更加喜歡將其比喻為字典裡面的目錄,根據字典來進行查詢的速度遠大於每一頁逐個逐個字排查的速度。

索引主要用於快速找出在某個列中有特定值的行,倘若不使用索引,mysql必須從第一條記錄開始讀完整個表,直到找出相關的行,表越大,查詢資料所花費的時間就越多。如果表中查詢的列有乙個索引,mysql能夠快速到達乙個位置去搜尋資料,而不必查詢所有資料,那麼將會節省很大一部分時間。

mysql索引的資料結構是樹,常用的儲存引擎innodb採用的是b+tree。這裡對b+tree及其相關的

innodb儲存檔案結構

.frm 表結構檔案

.ibd 資料檔案,ibd既包括資料也包括索引

表資料檔案本身就是按b+tree組織的乙個索引結構檔案,主鍵索引葉節點包含了完整的資料記錄

聚集索引一般是表中的主鍵索引,如果表中沒有顯示指定主鍵,則會選擇表中的第乙個不允許為null的唯一索引,如果還是沒有的話,就採用innodb儲存引擎為每行資料內建的6位元組rowid作為聚集索引。

mysql索引實現

在mysql中,索引屬於儲存引擎級別的概念,不同儲存引擎對索引的實現方式是不同的,本文主要討論myisam和innodb兩個儲存引擎的索引實現方式。

這裡設表一共有三列,假設我們以col1為主鍵,則圖8是乙個myisam表的主索引(primary key)示意。可以看出myisam的索引檔案僅僅儲存資料記錄的位址。在myisam中,主索引和輔助索引(secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。如果我們在col2上建立乙個輔助索引,則此索引的結構如下圖所示:

圖9同樣也是一顆b+tree,data域儲存資料記錄的位址。因此,myisam中索引檢索的演算法為首先按照b+tree搜尋演算法搜尋索引,如果指定的key存在,則取出其data域的值,然後以data域的值為位址,讀取相應資料記錄。

myisam的索引方式也叫做「非聚集」的,之所以這麼稱呼是為了與innodb的聚集索引區分。

innodb索引實現

雖然innodb也使用b+tree作為索引結構,但具體實現方式卻與myisam截然不同。

第乙個重大區別是innodb的資料檔案本身就是索引檔案。從上文知道,myisam索引檔案和資料檔案是分離的,索引檔案僅儲存資料記錄的位址。而在innodb中,表資料檔案本身就是按b+tree組織的乙個索引結構,這棵樹的葉節點data域儲存了完整的資料記錄。這個索引的key是資料表的主鍵,因此innodb表資料檔案本身就是主索引。

圖10圖10是innodb主索引(同時也是資料檔案)的示意圖,可以看到葉節點包含了完整的資料記錄。這種索引叫做聚集索引。因為innodb的資料檔案本身要按主鍵聚集,所以innodb要求表必須有主鍵(myisam可以沒有),如果沒有顯式指定,則mysql系統會自動選擇乙個可以唯一標識資料記錄的列作為主鍵,如果不存在這種列,則mysql自動為innodb表生成乙個隱含字段作為主鍵,這個字段長度為6個位元組,型別為長整形。

第二個與myisam索引的不同是innodb的輔助索引data域儲存相應記錄主鍵的值而不是位址。換句話說,innodb的所有輔助索引都引用主鍵作為data域。例如,圖11為定義在col3上的乙個輔助索引:

這裡以英文本元的ascii碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜尋十分高效,但是輔助索引搜尋需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。

了解不同儲存引擎的索引實現方式對於正確使用和優化索引都非常有幫助,例如知道了innodb的索引實現後,就很容易明白為什麼不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段作為主鍵在innodb中不是個好主意,因為innodb資料檔案本身是一顆b+tree,非單調的主鍵會造成在插入新記錄時資料檔案為了維持b+tree的特性而頻繁的**調整,十分低效,而使用自增字段作為主鍵則是乙個很好的選擇。

b+tree中乙個節點就可以存放很多個索引列資料,一次io就可以拿到很多資料,mysql預設的乙個節點16k的大小,可以通過show global status like 「innodb_page_size」 看到該值是16384,每次io讀取16k大小的資料,以索引列是bigint型別為例,大小8位元組,每一條資料還有乙個指向下一層的指標6位元組,16384/(8+6)=1170,乙個節點就大約可以存1170條資料。

以乙個層高為3的樹為例,葉子節點存放資料之後大小1kb,那麼這個樹可以存放 1170 *1170 *16 =21,902,400,大約2200萬條資料。所以在這種千萬級的表中通過主鍵索引查詢一條資料,最多3次io就可以找到一條資料。而很多時候樹的根節點基本都是在記憶體中,所以多數時候只需要2次io。

葉子節點之間也有雙向指標連線,提高區間範圍效能,範圍查詢。

建立索引的時候,可以選擇索引資料型別,乙個是btree乙個是hash,hash查詢當然也快,但是當遇到範圍查詢的時候hash就尷尬了,所以根據實際業務需求來看是用btree還是hash。

如何實現索引覆蓋?

參考:參考:

參考:

mysql索引深入解析

1.什麼是b tree 2.b tree在兩大引擎下的體現形式 3.理解幾大索引原則 推薦乙個資料結構視覺化的 在參與開發的第乙個專案中,有乙個特別嚴重的問題就是mysql的sql優化,sql優化的基礎就是索引,我發現我根本沒有理解mysql的索引,所以我重新學習了一下索引。索引是為了加速對錶中資料...

MySQL索引原理之索引原理

索引定義 是儲存引擎用於快速查詢記錄的一種資料結構。需要額外開闢空間和資料維護工作。索引是物理資料頁儲存,在資料檔案中 innodb,ibd檔案 利用資料頁 page 儲存。索引可以加快檢索速度,但是同時也會降低增刪改操作速度,索引維護需要代價。索引涉及的理論知識 二分查詢法 hash和b tree...

MySQL 索引解析

如果a的x次方等於n a 0,且a不等於1 那麼數x叫做以a為底n的對數 logarithm 記作x logan 通過上面的分析,我們知道io次數取決於b 數的高度 h,假設當前資料表的資料為 n,每個磁碟塊的資料項的數量是 m,則有h m 1 n,當資料量n一定的情況下,m越大,h越小 而m 磁碟...