1. 程式人生 > 其它 >資料庫原理一---MySQL基本架構與索引

資料庫原理一---MySQL基本架構與索引

MySQL基本架構

Server層包括聯結器、查詢快取、分析器、優化器、執行器等,所有跨儲存引擎的功能都在這一層實現。
儲存引擎層負責資料的儲存和提取。其架構模式是外掛式的,支援InnoDB(5.5後成為預設儲存引擎)、MyISAM、Memory等多個儲存引擎。

Server層

  • 聯結器
    負責使用者登入資料庫,進行使用者的身份認證,包括校驗賬戶密碼,許可權等操作。

  • 查詢快取
    客戶端與服務端建立連線後,MySQL在執行查詢語句時會先查詢快取,校驗這條SQL是不是在之前執行過。之前執行過的語句及其結果會以key-value對的形式被直接快取在記憶體中。(不建議使用查詢快取,查詢快取的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢快取都會被清空。在MySQL8.0中已刪除該功能)

  • 分析器
    分析SQL語句的作用,主要分為以下兩步
    1.詞法分析,提取關鍵字
    2.語法分析,判斷SQL語句是否正確

  • 優化器
    對SQL語句進行自動優化,對語法分析樹的形態進行修改,把語法分析樹變為查詢樹,確定執行方案。

  • 執行器
    執行語句。首先校驗使用者是否有執行查詢的許可權,如果有許可權,就會去呼叫引擎的介面,返回介面執行的結果。

儲存引擎

常用的儲存引擎有以下幾種:

  • InnoDB引擎
    Innodb引擎提供了對資料庫ACID事務的支援。並且還提供了行級鎖和外來鍵的約束。它的設計的目標就是處理大資料容量的資料庫系統。
  • MyIASM引擎
    不提供事務的支援,也不支援行級鎖和外來鍵。
  • MEMORY引擎
    所有的資料都在記憶體中,資料的處理速度快,但是安全性不高。

MyISAM與InnoDB的區別


關於全文索引:MySQL全文索引在5.7之前只支援英文,5.7之後內建了ngram全文檢索外掛,用來支援中文分詞,對MyISAM和InnoDB引擎都有效。
該處具體到底如何筆者也仍然存在疑問,難以給出準確回答,但是在更多情況下,全文索引我們更傾向於使用elasticSearch等工具實現全文檢索。

MySQL索引

索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標。
索引是一種資料結構。資料庫索引,是資料庫管理系統中一個排序的資料結構,以協助快速查詢、更新資料庫表中資料。
更通俗的說,索引就相當於目錄。為了方便查詢書中的內容,通過對內容建立索引形成目錄。索引是一個檔案,它是要佔據物理空間的。

索引是在儲存引擎層實現的,而不是在伺服器層實現的,所以不同儲存引擎具有不同的索引型別和實現。
在MySQL中使用較多的索引有Hash索引,B+樹索引等,而InnoDB儲存引擎和MyISAM儲存引擎的預設索引實現都為B+樹索引。
對於雜湊索引來說,底層的資料結構就是雜湊表,因此在絕大多數需求為單條記錄查詢的時候,可以選擇雜湊索引,查詢效能最快;其餘大部分場景,建議選擇BTree索引。

索引的基本原理

索引用來快速地尋找那些具有特定值的記錄。如果沒有索引,一般來說執行查詢時遍歷整張表。
索引的原理很簡單,就是把無序的資料變成有序的查詢

  1. 把建立了索引的列的內容進行排序

  2. 對排序結果生成倒排表

  3. 在倒排表內容上拼上資料地址鏈

  4. 在查詢的時候,先拿到倒排表內容,再取出資料地址鏈,從而拿到具體資料

B+ Tree

B Tree 指的是 Balance Tree,也就是平衡樹。平衡樹是一顆查詢樹,並且所有葉子節點位於同一層。
B+ Tree 是基於 B Tree 和葉子節點順序訪問指標進行實現,它具有 B Tree 的平衡性,並且通過順序訪問指標來提高區間查詢的效能。
在 B+ Tree 中,一個節點中的 key 從左到右非遞減排列,如果某個指標的左右相鄰 key 分別是 keyi 和 keyi+1,且不為 null,則該指標指向節點的所有 key 大於等於 keyi 且小於等於 keyi+1。

B+樹的查詢、插入、刪除
進行查詢操作時,首先在根節點進行二分查詢,找到一個 key 所在的指標,然後遞迴地在指標所指向的節點進行查詢。直到查詢到葉子節點,然後在葉子節點上進行二分查詢,找出 key 所對應的 data。

插入刪除操作記錄會破壞平衡樹的平衡性,因此在插入刪除操作之後,需要對樹進行一個分裂、合併、旋轉等操作來維護平衡性。

為什麼InnoDB及MyISAM引擎都使用了B+Tree作為索引

B+Tree與紅黑樹的比較
紅黑樹等平衡樹也可以用來實現索引,但是檔案系統及資料庫系統普遍採用 B+ Tree 作為索引結構,主要有以下兩個原因:

  1. 更少的查詢次數
    平衡樹查詢操作的時間複雜度等於樹高 h,而樹高大致為 O(h)=O(logdN),其中 d 為每個節點的出度。 紅黑樹的出度為 2,而 B+ Tree 的出度一般都非常大,所以紅黑樹的樹高 h 很明顯比 B+ Tree 大非常多,檢索的次數也就更多。

  2. 利用計算機預讀特性
    為了減少磁碟 I/O,磁碟往往不是嚴格按需讀取,而是每次都會預讀。預讀過程中,磁碟進行順序讀取,順序讀取不需要進行磁碟尋道,並且只需要很短的旋轉時間,因此速度會非常快。
    作業系統一般將記憶體和磁碟分割成固態大小的塊,每一塊稱為一頁,記憶體與磁碟以頁為單位交換資料。資料庫系統將索引的一個節點的大小設定為頁的大小,使得一次 I/O 就能完全載入一個節點,並且可以利用預讀特性,相鄰的節點也能夠被預先載入。

B+Tree與BTree的比較
B樹只適合隨機檢索,而B+樹同時支援隨機檢索和順序檢索

  1. B樹只適合隨機檢索,而B+樹同時支援隨機檢索和順序檢索

  2. B+樹空間利用率更高,可減少I/O次數,磁碟讀寫代價更低。
    一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟I/O消耗。
    B+樹的內部結點並沒有指向關鍵字具體資訊的指標,只是作為索引使用,其內部結點比B樹小,盤塊能容納的結點中關鍵字數量更多,一次性讀入記憶體中可以查詢的關鍵字也就越多,相對的,IO讀寫次數也就降低了。而IO讀寫次數是影響索引檢索效率的最大因素。

  3. B+樹的查詢效率更加穩定
    B樹搜尋有可能會在非葉子結點結束,越靠近根節點的記錄查詢時間越短,只要找到關鍵字即可確定記錄的存在,其效能等價於在關鍵字全集內做一次二分查詢。
    而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查詢都必須走一條從根節點到葉節點的路,所有關鍵字的查詢路徑長度相同,導致每一個關鍵字的查詢效率相當。

  4. B樹在提高了磁碟IO效能的同時並沒有解決元素遍歷的效率低下的問題。
    B+樹的葉子節點使用指標順序連線在一起,只要遍歷葉子節點就可以實現整棵樹的遍歷,而B樹不支援這樣的操作。

  5. 增刪檔案(節點)時,B+樹效率更高。
    因為B+樹的葉子節點包含所有關鍵字,並以有序的連結串列結構儲存,這樣可很好提高增刪效率。

B+樹與hash索引

  1. hash索引進行等值查詢更快,但是卻無法進行範圍查詢,且等值查詢不穩定,效能不可預測
    當某個鍵值存在且大量重複的時候,發生hash碰撞,此次hash索引效率可能極差
    b+樹的查詢效率比較穩定,對於所有的查詢都是從根節點到葉子節點,且樹的高度較低

  2. hash索引不支援使用索引進行排序

  3. hash索引不支援模糊查詢以及多列索引的最左字首匹配

  4. hash索引任何時候都避免不了回表查詢,而B+樹在符合某些條件的時候可以只通過索引完成查詢

B+樹對比二叉樹
二叉樹當資料庫的資料量特別大時,其層數也特別大。磁碟IO的次數會由樹的高度決定,不使用二叉樹是為了壓縮樹的高度,減少磁碟IO的次數。

InnoDB、MyISAM下索引實現的差異

MyISAM索引實現
MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是資料記錄的地址。
MyISAM會按照資料插入的順序分配行號,從0開始,然後按照資料插入的順序儲存在磁碟上。因為行是定長的,所以可以從表的開頭跳過相應的位元組找到需要的行。
MyISAM的索引檔案僅僅儲存資料記錄的行號,然後通過此行號回表查詢需要的資料

在MyISAM中,主索引和輔助索引在結構上沒有任何區別,只是主索引要求Key是唯一的,而輔助索引的key可以重複。

因此,MyISAM中索引檢索的演算法為首先按照B+Tree搜尋演算法搜尋索引,如果指定的key存在,則取出其data域的值,然後以data域的值為地址,讀取相應資料記錄。MyISAM的索引方式索引和資料存放是分開的,非聚集的。

InnoDB索引實現
雖然InnoDB也使用B+Tree作為索引結構,但具體實現方式卻與MyISAM截然不同。在InnoDB中,表資料檔案本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域儲存了完整的資料記錄。這個索引的key是資料表的主鍵,因此InnoDB表資料檔案本身就是主索引。
聚簇索引的每一個葉子節點都包含了主鍵值、事務ID、用於事務和MVCC的回滾指標以及所有的剩餘列。
InnoDB的二級索引的葉子節點儲存的不是行號(行指標),而是主鍵列。這種策略的缺點是二級索引需要兩次索引查詢,第一次在二級索引中查詢主鍵,第二次在聚簇索引中通過主鍵查詢需要的資料行。

綜上,兩者都包含非聚簇索引的實現,但是InnoDB引擎支援了聚簇索引。