MySQL(二):快速理解MySQL數據庫索引

索引

基本概念:索引是在存儲引擎層實現的,而不是在服務器層實現的,因此不一樣存儲引擎具備不一樣的索引類型和實現。mysql

數據結構

  • Tree 指的是 Balance Tree,也就是平衡樹。平衡樹是一顆查找樹,而且全部葉子節點位於同一層。
  • B+ Tree 是基於 B Tree 和葉子節點順序訪問指針進行實現,它具備 B Tree 的平衡性,而且經過順序訪問指針來提升區間查詢的性能。
  • 在 B+ Tree 中,一個節點中的 key 從左到右非遞減排列,若是某個指針的左右相鄰 key 分別是 keyi 和 keyi+1,且不爲 null,則該指針指向節點的全部 key 大於等於 keyi 且小於等於 keyi+1。

基本原理

  • 進行查找操做時,首先在根節點進行二分查找,找到一個 key 所在的指針,而後遞歸地在指針所指向的節點進行查找。直到查找到葉子節點,而後在葉子節點上進行二分查找,找出 key 所對應的 data。
  • 插入刪除操做會破壞平衡樹的平衡性,所以在進行插入刪除操做以後,須要對樹進行分裂、合併、旋轉等操做來維護平衡性。

紅黑樹

紅黑樹等平衡樹也能夠用來實現索引,可是文件系統及數據庫系統廣泛採用 B+ Tree 做爲索引結構,這是由於使用 B+ 樹訪問磁盤數據有更高的性能。sql

  • B+ 樹有更低的樹高:平衡樹的樹高 O(h)=O(logdN),其中 d 爲每一個節點的出度。紅黑樹的出度爲 2,而 B+ Tree 的出度通常都很是大,因此紅黑樹的樹高 h 很明顯比 B+ Tree 大很是多。
  • 磁盤訪問原理:操做系統通常將內存和磁盤分割成固定大小的塊,每一塊稱爲一頁,內存與磁盤以頁爲單位交換數據。數據庫系統將索引的一個節點的大小設置爲頁的大小,使得一次 I/O 就能徹底載入一個節點。

    若是數據不在同一個磁盤塊上,那麼一般須要移動制動手臂進行尋道,而制動手臂由於其物理結構致使了移動效率低下,從而增長磁盤數據讀取時間。B+ 樹相對於紅黑樹有更低的樹高,進行尋道的次數與樹高成正比,在同一個磁盤塊上進行訪問只須要很短的磁盤旋轉時間,因此 B+ 樹更適合磁盤數據的讀取。
  • 磁盤預讀特性:爲了減小磁盤 I/O 操做,磁盤每每不是嚴格按需讀取,而是每次都會預讀。預讀過程當中,磁盤進行順序讀取,順序讀取不須要進行磁盤尋道,而且只須要很短的磁盤旋轉時間,速度會很是快。而且能夠利用預讀特性,相鄰的節點也可以被預先載入。

索引分類

B+樹索引

  1. 是大多數 MySQL 存儲引擎的默認索引類型。
  2. 由於再也不須要進行全表掃描,只須要對樹進行搜索便可,因此查找速度快不少。
  3. 由於 B+ Tree 的有序性,因此除了用於查找,還能夠用於排序和分組。
  4. 能夠指定多個列做爲索引列,多個索引列共同組成鍵。
  5. 適用於全鍵值、鍵值範圍和鍵前綴查找,其中鍵前綴查找只適用於最左前綴查找。若是不是按照索引列的順序進行查找,則沒法使用索引。
  6. InnoDB 的 B+Tree 索引分爲聚簇索引(主索引)和非聚簇索引(輔助索引)。
  7. 惟一索引:主鍵就是一種特殊的惟一索引,惟一索引容許null值,但主鍵列不容許爲null值,一張表最多建議一個主鍵

哈希索引

  1. 哈希索引能以O(1)時間進行查找,可是失去了有序性特色InnoDB
  2. 存儲引擎有一個特殊的功能叫「自適應哈希索引」,當某個索引值被使用的很是頻繁時,會在 B+Tree 索引之上再建立一個哈希索引,這樣就讓 B+Tree 索引具備哈希索引的一些優勢,好比快速的哈希查找。

全文索引

  1. MyISAM 存儲引擎支持全文索引,用於查找文本中的關鍵詞,而不是直接比較是否相等。
  2. 查找條件使用 MATCH(clo1,clo2..) AGAINST(value),而不是普通的 WHERE。全文索引使用倒排索引實現,它記錄着關鍵詞到其所在文檔的映射。
  3. InnoDB 存儲引擎在 MySQL 5.6.4 版本中也開始支持全文索引。
    FULLTEXT (clo1,clo2)只有創建的全文索引的列能夠進行全文索引

索引優化

獨立的列

進行查詢時,索引列不能是表達式的一部分,也不能是函數的參數,不然沒法使用索引數據庫

多列索引

在須要使用多個列做爲條件進行查詢時,使用多列索引比使用多個單列索引性能更好。
列以下面的語句中能夠將actor_id和film_id設置多列索引性能優化

SELECT film_id, actor_ id FROM sakila.film_actor
WHERE actor_id = 1 AND film_id = 1;

索引列的順序

索引的選擇性是指:不重複的索引值和記錄總數的比值。最大值爲 1,此時每一個記錄都有惟一的索引與其對應。選擇性越高,每一個記錄的區分度越高,查詢效率也越高。
讓選擇性最強的索引列放在最前面
輸入語句:服務器

SELECT COUNT(DISTINCT addr_id)/COUNT(*) AS addr_id_selectivity,
COUNT(DISTINCT user_id)/COUNT(*) AS user_id_selectivity,
COUNT(*)
FROM user_address;

結果:數據結構

addr_id_selectivity:1.0000
user_id_selectivity:0.1250
count(*):64
從上述結果分析:主鍵是惟一的,user_id會有重複,因此寫sql語句時,主鍵應該放在最前面
這樣能夠逐個分析對應的索引函數

前綴索引

  • 對於 BLOB、TEXT 和 VARCHAR 類型的列,必須使用前綴索引,只索引開始的部分字符。
  • 前綴長度的選取須要根據索引選擇性來肯定。某些列,通常是字符串類型,很長,所有做爲索引大大增長存儲空間,索引也須要維護,對於長字符串,又想做爲索引列,一個可取的辦法就是取前一部分(前綴),表明一整列做爲索引串。
  • 如何確保這個前綴能表明或大體表明這一列?因此mysql中有個概念是索引的選擇性,是指索引中不重複的值的數目(也稱基數)與整個表該列記錄總數(#T)的比值,好比一個列表(1,2,2,3),總數是4,不重複值數目爲3,選擇性爲3/4,所以選擇性範圍是[1/#T, 1],這個值越大,表示列中不重複值越多,越適合做爲前綴索引,惟一索引(UNIQUE KEY)的選擇性是1。

MySQL性能優化神器Explain使用分析

  • Explain 用來分析 SELECT 查詢語句,開發人員能夠經過分析 Explain 結果來優化查詢語句。
    • select_type : 查詢類型,有簡單查詢、聯合查詢、子查詢等
    • key : 使用的索引
    • rows : 掃描的行數

總結

  • 數據庫只作兩件事情:存儲數據、檢索數據。而索引是在你存儲的數據以外,額外保存一些路標(通常是B+樹),以減小檢索數據的時間。因此索引是主數據衍生的附加結構。
  • 一張表能夠創建任意多個索引,每一個索引能夠是任意多個字段的組合。索引可能會提升查詢速度(若是查詢時使用了索引),但必定會減慢寫入速度,由於每次寫入時都須要更新索引,因此索引只應該加在常常須要搜索的列上,不要加在寫多讀少的列上。
  • 多使用explain對語句進行索引分析,任何理論都是創建在實際的分析基礎上,explain語句關注那幾個關鍵詞便可。盲目的加索引並非好的,有時候索引反而成爲拖慢咱們系統運行速度的源頭.優化索引其實就兩件事,第一找到區別度大的列,第二看生產的查詢場景是否有用到這個列,加上索引用explain分析,看是否會比不加上索引性能提高更快
相關文章
相關標籤/搜索