MySQL系列(四) MySQL的索引和算法

  • 11 表結構

    • 表是關於特定實體的數據集合,這也是關係型數據庫的核心。
    • 在InnoDB中,表都是根據主鍵順序組織存放的,這種存儲方式的表成爲索引組織表。
    • 全部數據都被邏輯的存放在一個空間中,稱之爲表空間 tablespace。 表空間又由段 segment, 區 extent, 頁page 組成。 頁在一些文檔中有時也稱之爲塊 block。
    • 一個區通常爲1M,一個頁老是16KB,即一個區一共有64個連續的頁。
    • InnoDB中數據是按行進行存放的。每一個頁存放的行是有硬性規定規定的,最多運行存放16 KB/2-200行數據,即7992行記錄。另外也有面向列的數據庫,優勢是分析類SQL語句的執行及數據壓縮是很是有效的。面向列是當前數據庫發展的一個方向。
    • 內部是按照一種鏈表的結構來串連各個行記錄的,當前位置的記錄加上偏移量就是下條記錄的起始地址。
    • 行數據溢出,當行中數據過大時,頁中只保留了前786字節的前綴數據,以後是偏移量,指向行溢出頁。
  • 12 索引

    • B+樹索引算法

      • 平衡二叉樹的左旋和右旋數據庫

         

         

      • 概述數組

        B+樹是爲磁盤或其餘直接存取輔助設備設計的一種平衡查找樹。緩存

        在B+樹中,全部記錄節點都是按鍵值的大小順序存放在同一層的葉子節點上,由各葉子節點指針進行鏈接。函數

        B+樹索引在數據庫中有一個特色是高扇出性,所以在數據庫中,B+樹的高度通常都在2~4層,這也就是說查找某一鍵值的行記錄時最多隻須要2到4次IO。性能

        數據庫中的B+樹索引能夠分爲彙集索引(clustered inex)和輔助索引(secondary index),可是不論是彙集仍是輔助的索引,其內部都是B+樹的,即高度平衡的,葉子節點存放着全部的數據。彙集索引與輔助索引不一樣的是,葉子節點存放的是不是一整行的信息。優化

      • 彙集索引spa

        • 彙集索引構造圖設計

           

        InnoDB 存儲引擎表是索引組織表,即表中數據按照主鍵順序存放。而彙集索引就是每張表根據主鍵構造一棵B+樹,葉子節點中存放的即爲整張表的行記錄數據,也將彙集索引的葉子節點稱爲數據頁。指針

        彙集索引的這個特性決定了索引組織表中數據也是索引的一部分。每一個數據頁都經過一個雙向鏈表來進行連接。 數據頁的排序只能按照一顆B+樹進行,這也是每張表只能擁有一個彙集索引的根本緣由。

        在多數狀況下,查詢優化器傾向於採用彙集索引。由於彙集索引可以在B+樹索引的葉子節點上直接找到數據。

        此外,因爲定義了數據的邏輯順序,彙集索引可以特別快地訪問針對範圍值的查詢。注:好比查詢倒數10個主鍵元素,數據頁是雙向鏈表進行連接的;好比範圍查詢,查詢500-1000的主鍵元素,主鍵都是順序存放的,能夠直接按照區間查詢。

        數據頁上存放的是完整的每行的記錄,而在非數據頁的索引頁中,存放的僅僅是鍵值及指向數據頁的偏移量,而不是一個完整的行記錄。

        注:

        • 每張表中有一個彙集索引頁和一個或多個輔助索引頁,彙集索引頁存放的便是每一個主鍵和數據頁的映射關係。主鍵是按照順序存放,查詢時使用二分查找。
        • 數據頁的子級單位並不直接是行,而是槽,槽的子級單位纔是行。每一個數據頁中保存必定數量的槽,每一個槽中保存4-8個行記錄。
        • 經過彙集索引的頭節點數據,能夠查詢到對應的數據頁、槽、槽中行記錄的偏移量。數據頁中保存着行記錄的起始和結束位置。每一個行記錄的頭節點又保存着下一個行記錄的相對偏移量。
        • 所以經過主鍵就能夠完成一張表的掃描。
        • 彙集索引和非彙集索引其實是不一樣的B+樹,且彙集索引有且只有一顆B+樹,非彙集索引則根據索引的類型分別創建一顆。
      • 輔助索引(非彙集索引)

        • 輔助索引構造圖

           

        對於輔助索引,葉子節點並不包含行記錄的所有數據。

        葉子節點除了包含鍵值之外,每一個葉子節點中的索引行中還包含了一個書籤

        該書籤用來告訴 InnoDB 存儲引擎哪裏能夠找到與索引相對應的行數據。書籤存放的便是相應行的彙集索引。

        輔助索引的存在並不影響數據在彙集索引中的組織,所以每張表上能夠有多個輔助索引。

        當經過輔助索引來尋找數據時,InnoDB 存儲引擎會遍歷輔助索引並經過葉級別的指針得到對應的彙集索引,而後再經過彙集索引來找到一個完整的行記錄。

        舉例來講,若是在一棵高度爲3的輔助索引樹中查找數據,那須要對這棵輔助索引樹遍歷3次找到指定彙集索引,若是彙集索引樹的高度一樣爲3,那麼還須要對彙集索引樹進行3次查找,最終找到一個完整的行數據所在的頁,所以一共須要6次邏輯IO訪問以獲得最終的一個數據頁,槽中的查找由於在內存中不算一次IO。

        對於其餘的一些數據庫,如Microsoft SQL Server數據庫,其有一種稱爲堆表的表類型,即行數據的存儲按照插入的順序存放。堆表的特性決定了堆表上的索引都是非彙集的,主鍵與非主鍵的區別只是是否惟一且非空。所以這時書籤是一個行標識符,能夠用如「文件號:頁號:槽號」的格式來定位實際的行數據。

        • 覆蓋索引

          從輔助索引上就能夠獲得所需數據,而不用再經過主鍵進行索引。

          由於輔助索引存放的索引列和對應的值,以及書籤。

        • 聯合索引

          • 聯合索引結構圖

             

          指對錶上的多個列創建索引。

          聯合索引是根據第一個索引值進行排序的,所以頁適用於第一個索引的查詢。好比(a,b),適用於 where a=xx 而不適用於 where b=xx 。

          聯合索引的第二個好處是已經對第二個鍵值進行了排序處理。例如,在不少狀況下應用程序都須要查詢某個用戶的購物狀況,並按照時間進行排序,最後取出最近三次的購買記錄,這時使用聯合索引能夠避免多一次的排序操做,由於索引自己在葉子節點已經排序了。

      • OLTP 和 OLAP 中 B+樹的使用概述

        在瞭解了B+樹索引的本質和實現後,下一個須要考慮的問題是怎樣正確地使用B+樹索引。

        在OLTP應用中,查詢操做只從數據庫中取得一小部分數據,甚至在不少時候只取1條記錄,如根據主鍵值來取得用戶信息,根據訂單號取得訂單的詳細信息,這都是典型OLTP應用的查詢狀況。在這種狀況下,B+樹索引創建後,對該索引的使用應該只是經過該索引取得表中少部分的數據。這時創建B+樹索引纔是有意義的,不然即便創建了,優化器也可能選擇不使用索引。

        對於OLAP應用,狀況可能就稍顯複雜了。不過歸納來講,在OLAP應用中,都須要訪問表中大量的數據,根據這些數據來產生查詢的結果,這些查詢可能是面向分析的查詢,目的是爲決策者提供支持。如這個月每一個用戶的消費狀況,銷售額同比、環比增加的狀況。所以在OLAP中索引的添加根據的應該是宏觀的信息,而不是微觀,由於最終要獲得的結果是提供給決策者的。例如不須要在OLAP中對姓名字段進行索引,由於不多須要對單個用戶進行查詢。可是對於OLAP中的複雜查詢,要涉及多張表之間的聯接操做,所以索引的添加依然是有部分意義的。

    • 全文索引

      • 概述

        全文檢索(Full-Text Search)是將存儲於數據庫中的整本書或整篇文章中的任意內容信息查找出來的技術。它能夠根據須要得到全文中有關章、節、段、句、詞等信息,也能夠進行各類統計和分析。

      • 倒排索引

        全文檢索一般使用倒排索引來實現。倒排索引同B+樹索引同樣,也是一種索引結構。它在輔助表中存儲了單詞與單詞自身在一個或多個文檔中所在位置之間的映射。這一般利用關聯數組實現。

        數據的表現形式之一爲:

        • full invertedindex,其表現形式爲{單詞,(單詞所在文檔的ID,在具體文檔中的位置)}

        全文檢索的表中,有兩個列: word 和 ilist。word上設有索引。

        輔助表:倒排索引中存放 word 字段的物理表

      • 全文檢索索引緩存

        全文檢索索引緩存採用紅黑樹結構,根據(word, ilist) 進行排序。

        實現很是複雜,主要目的是爲了提供全文索引的緩存,提升全文檢索的性能。

    • 哈希索引

      InnoDB存儲引擎使用哈希算法來對字典進行查找,其衝突機制採用鏈表方式,哈希函數採用除法散列方式。

      對於緩衝池頁的哈希表來講,在緩衝池中的Page頁都有一個chain指針,它指向相同哈希函數值的頁。而對於除法散列,m的取值爲略大於2倍的緩衝池頁數量的質數。例如:當前參數innodb_buffer_pool_size的大小爲10M,則共有640個16KB的頁。對於緩衝池頁內存的哈希表來講,須要分配640×2=1280個槽,可是因爲1280不是質數,須要取比1280略大的一個質數,應該是1399,因此在啓動時會分配1399個槽的哈希表,用來哈希查詢所在緩衝池中的頁。

      InnoDB存儲引擎的表空間都有一個表ID,用戶所要查詢的應該是某個表空間的某個連續16KB的頁,即偏移量offset。InnoDB存儲引擎將space_id左移20位,而後加上這個space_id和offset,即關鍵字K=space_id<<20+space_id+offset,而後經過除法散列到各個槽中去。

      • 自適應哈希索引 AHI

        InnoDB存儲引擎會監控對錶上各索引頁的查詢。若是觀察到創建哈希索引能夠帶來速度提高,則創建哈希索引,稱之爲自適應哈希索引。

        AHI 是經過緩衝池的B+樹頁構造而來,所以創建的速度很快,並且不須要對整張表構建哈希索引。InnoDB存儲引擎會自動根據訪問的頻率和模式來自動地爲某些熱點頁創建哈希索引

        自適應哈希索引僅是數據庫自身建立並使用的,DBA自己並不能對其進行干預。自適應哈希索引經哈希函數映射到一個哈希表中,所以對於字典類型的查找很是快速,如 where id=1;

        自適應哈希索引創建的條件

        • 對這個頁的連續訪問模式必須是同樣的。
        • 以該模式訪問了100次
        • 頁經過該模式訪問了N次,N=表中記錄 * 1/16

        自適應哈希索引的優點

        • 讀取和寫入速度能夠提升2倍
        • 輔助索引的鏈接操做性能提升5倍
相關文章
相關標籤/搜索