索引是幫助MySQL 高效獲取數據的排好序的數據結構。html
MySQL 默認使用的是B+Tree數據結構。數據庫
在介紹結構以前,先簡單說下磁盤的讀取原理:數據結構
操做系統讀寫磁盤的基本單位是扇區,而文件系統的基本單位是簇(Cluster)。併發
MySQL在存儲數據時數據都存儲在磁盤的一道道扇區中,磁盤是旋轉的,每次存儲的數據可能會存儲在不一樣的扇區中。高併發
在讀取時,磁道每次須要先進行尋道操做(速度慢),磁頭只能進行左右移動,每一次尋道都是一次I/O操做。性能
若是數據都存在同一磁道中,那麼旋轉磁盤(速度快)就能夠取到數據,不須要進行尋道操做,會大大減小開銷。網站
(這裏是我本身的理解,若是有不對的地方,歡迎你們指出來)操作系統
給你們推薦一個數據結構可視化網站,能夠直觀的演示各類結構3d
若是普通的一顆二叉樹,在極端狀況下會退化成鏈表結構。如圖: 指針
和二叉樹同樣,在數據量大的狀況下,樹的深度太大,查詢次數太高。
好比,有500W的數據,假如樹的高度有20層,你要查詢的數據恰好在葉子節點,那麼須要進行20次尋道操做,和磁盤進行20次I/O交互操做,大大加大了開銷。
HASH索引,相比較於B-Tree 而言,不須要從根節點到葉子節點的遍歷,能夠一次定位到位置,查詢效率更高,但缺點也很明顯:
僅能知足全值查詢,不能使用範圍查詢。由於是經過HASH值進行計算,HASH值是沒規律的,因此只能精確查詢,不能保證順序和原來一致,因此不行進行範圍查詢。
不能進行排序,緣由如上。
HASH碰撞。
B+Tree 是平衡樹的一種,而且全部葉子節點位於同一層,是不會退化成鏈表結構的。
B+Tree 有一個度的概念,指節點的數據存儲個數。度越大,節點保存的數據個數就越多。那麼相應的樹的高度下降,在進行查詢時,須要進行的I/O操做更少,讀取數據的速度更快。
非葉子節點不存儲data,只存儲key,能夠增大度。葉子節點只存儲data, 不存儲指針,順序訪問指針,能夠提升區間訪問的性能。
進行查找操做時,首先在根節點進行二分查找,找到一個key所在的指針,而後遞歸的在指針所指向的節點進行查找。直到查找到葉子節點,而後在葉子節點上進行二分查找,找出 key 所對應的 data。
通常使用磁盤I/O次數評價索引結構的優劣
預讀:磁盤通常會順序向後讀取必定長度的數據(頁的整數倍)放入內存。
局部性原理:當一個數據被用到時,其附近的數據也一般會立刻被使用。
B+Tree 節點的大小設爲等於一個頁,每次新建節點直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,就實現了一個節點的載入只需一次I/O。
B+Tree 的度通常會超過100,所以高度很是小(通常爲3到5之間)
MyISAM 索引文件和數據文件是分離的。
MyISAM 引擎使用B+Tree 做爲索引結構,MyISAM的索引文件僅僅保存數據記錄的地址。
MyISAM中,主索引和輔助索引在結構上沒有任何區別,只是主索引要求key是惟一的,而輔助索引的key能夠重複。
數據文件自己就是索引文件。
InnoDB 引擎也使用B+Tree 做爲索引結構,葉節點包含了完整的數據記錄。
InnoDB的數據文件自己要按主鍵彙集,因此InnoDB要求表必須有主鍵(MyISAM能夠沒有)。
InnoDB中,主鍵索引包含了完整的數據記錄,而輔助索引都引用主鍵做爲data域。
知道了InnoDB的索引實現後,就明白了爲何不建議使用過長的字段做爲主鍵了,由於全部輔助索引都用主索引,過長的主索引會令輔助索引變得過大。
事物:InnoDB支持事務,可使用 Commit 和 Rollback 語句。MyISAM不支持。
併發:MyISAM 只支持表級鎖,而InnoDB 還支持行級鎖。
外鍵:InnoDB 支持外鍵,MyISAM不支持。
備份:InnoDB 支持在線熱備份,MyISAM不支持。
崩潰恢復:MyISAM 崩潰後發生損壞的機率比 InnoDB 高不少,並且恢復的速度也更慢。
其它特性:
InnoDB是彙集索引,MyISAM是非彙集索引。
InnoDB不保存表的具體行數,MyISAM用變量保存了整個表的行數。
InnoDB不支持全文索引,MyISAM支持全文索引。
MyISAM 支持壓縮表和空間數據索引。
主鍵索引:是一種特殊的惟一索引,不容許有空值。設定爲主鍵後數據庫會自動創建索引innodb爲彙集索引。
惟一索引:索引列中的值必須是惟一的,可是容許爲空值。
單值索引:索引只包含單個列,但一個表中能夠有多個單值索引。
複合索引:在表中的多個字段組合上建立的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引纔會被使用,使用組合索引時遵循最左前綴原則。
全文索引:只有在MyISAM引擎上才能使用,只能在CHAR、VARCHAR、TEXT類型字段上使用全文索引,在一堆文字中,經過其中的某個關鍵字等,就能找到該字段所屬的記錄行。好比有"怡紅院、金鳳樓"等等,能夠 經過金鳳樓,可能就能夠找到該條記錄。
空間索引:只有在MyISAM引擎上才能使用,建立空間索引的列,必須將其聲明爲NOT NULL。空間索引是對空間數據類型的字段創建的索引,MySQL中的空間數據類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。在建立空間索引時,使用SPATIAL關鍵字。
B+Tree 是按照第一個關鍵字進行索引,而後在葉子節點上按照第一個關鍵字、第二個關鍵字、第三個關鍵字…進行排序。使用複合索引的時候,會根據你的索引順序,從左開始匹配。
索引只能用於查找key是否存在(相等),遇到範圍查詢(>、<、between、like左匹配)等就不能進一步匹配了,後續退化爲線性查找。
提升查詢效率(下降IO使用率)。
下降CPU使用率, 例如:...order by age desc
,由於B+Tree 索引自己就是一個排好序的結構,所以在排序時能夠直接使用。
索引自己很大,實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引列也是要佔用空間。
索引會下降增刪改的效率,MySQL不只要保存數據,還要保存一下索引文件每次更新添加了索引列的字段, 都會調整由於更新所帶來的鍵值變化後的索引信息。
索引不是全部狀況均適用:A. 少許數據 B.頻繁更新的字段 C.不多使用的字段
主鍵自動創建惟一索引。
頻繁做爲查詢條件的字段應該建立索引,WHERE 後面的語句。
查詢中與其它表關聯的字段,外鍵關係創建索引。
單鍵/組合索引的選擇問題,who?在高併發下傾向建立組合索引。
查詢中排序的字段,排序字段若經過索引去訪問將大大提升排序速度。
查詢中統計或者分組字段。