MySQL 技術內幕——數據庫架構

如何設計一個數據庫?

要設計一個關係型數據庫,首先要劃分爲兩部分,存儲模塊和程序實例模塊,程序實例實現了對存儲模塊的管理。

關係型數據庫架構

其中索引管理和鎖管理是重點。

1、爲什麼要使用索引?

最基本的數據查詢方式便是全表掃描,全表掃描是非常慢的,需要避免。索引便是一種更高效的查詢機制。

2、什麼樣的信息能成爲索引?

主鍵、唯一鍵以及普通鍵。

3、索引的數據結構?

索引的數據結構分爲樹結構和 Hash 結構。

索引最簡單的樹結構便是二叉查找樹,還有平衡二叉樹、紅黑樹、B 樹、B+ 樹。MySQL 存儲引擎 InnoDB 的 B 樹索引便是通過 B+ 樹來實現的。

下面詳細看下這些數據結構,以體驗其優勢和劣勢:

(1) 二叉查找樹

特點:每個節點最多有兩個子樹,稱爲左子樹和右子樹;對於每個節點的值 x,其左子樹值均小於 x,右子樹的值均大於 x。

查找方式:二分查找。時間複雜度 O(logn)。

缺點:有可能變成線性的二叉樹,查詢時間複雜度會變爲 O(n),大大降低了查詢效率。

(2) 平衡二叉樹

特點:在二叉查找樹的基礎上,任意一個節點左子樹和右子樹的高度均不超過 1。

查找方式:二分查找,時間複雜度 O(logn)。

缺點:平衡二叉樹是利用樹的旋轉特性,來保證樹是平衡二叉樹,時間複雜度會維持在 O(logn),但是如果樹的深度特別深,就會增加大量的 IO 操作,其檢索性能會比全表掃描還要差很多。

那麼爲了即降低時間複雜度,又降低 IO 的次數,需要讓樹變的矮一些,每個節點能存儲的數據多一些,即引出了 B 樹。

(3) B 樹

B 樹又稱爲平衡多路查找樹,如果每個節點最有 m 個孩子,那麼這樣的樹便是 m 階 B 樹,下面是一個三階 B 樹:

三階 B 樹

特點:

  • 根節點至少包括兩個孩子;
  • 樹中每個節點最多含有 m 個孩子(m>=2);
  • 除根節點和葉子節點外,其他節點至少有 ceil(m/2) 個孩子,ceil 函數表示取上限,例如 ceil(3/2) = 2;
  • 所有葉子節點都位於同一層,即葉子節點的高度都是一樣的。

查找的時間複雜度 O(logn)。

(4) B+ 樹

B+ 樹是比 B 樹更優秀的數據結構。下面是一個三階 B+ 樹:

三階 B+ 樹

B+ 樹是 B 樹的變體,其定義基本與 B 樹相同,除了:

  • 非葉子節點的子樹指針與關鍵字個數相同;
  • 非葉子節點的子樹指針P[i],指向關鍵字值 [K[i], K[i+1]) 的子樹;
  • 非葉子節點僅用來做索引,數據都保存在葉子節點中;
  • 所有葉子節點均有一個鏈指針指向下一個葉子節點,並按大小順序鏈接,作用:方便直接在葉子節點做範圍統計。

B+ 樹所有的檢索都是從根部開始,檢索到葉子節點才能結束,非葉子節點僅用來做索引,不存儲數據,這樣非葉子節點就能存儲更多的關鍵字了,使得 B+ 樹比 B 樹更矮,IO 性能會更好。

查找的時間複雜度 O(logn)。

經過上面的分析,發現 B+ 樹更適合用來存儲索引,原因如下:

  • B+ 樹的磁盤 IO 代價更低;
  • B+ 樹查詢效率更加穩定;
  • B+ 樹更有利於對數據庫的掃描;

除了 B 樹索引,有些存儲引擎還支持 Hash 索引,例如 InnoDB。

Hash 索引

Hash 索引使用了 Hash 表來存儲索引,檢索只需要計算一次 Hash 值便可以定位 “桶” 的位置,然後把 “桶” 裏面的數據全部加載進內存,由於 “桶” 裏面的數據是一個鏈表,順着鏈表便可以定位到索引的位置。

Hash 索引的查詢效率理論上要比 B 樹索引高。既然 Hash 索引性能好,那麼爲什麼還要使用 B 樹索引呢?

這是因爲 Hash 索引是有缺點的:

  • 僅僅能滿足 “=” “IN”,不能使用範圍查詢;
  • 無法被用來避免數據的排序操作;
  • 不能利用部分索引鍵查詢;
  • 不能避免表掃描,Hash 索引是將索引鍵通過 Hash 運算之後,將 Hash 值和所對應行指針信息存放在鏈表節點中的,由於不同索引鍵存在相同 Hash 值,所以即使取出數據,也無法直接完成查詢,還需要訪問鏈表節點中的實際數據進行相應的比較;
  • 遇到大量 Hash 值相等的情況後,性能並不一定就會比 B 樹索引高。

除了 B 樹索引,Hash 索引,還有一些數據庫支持 BitMap 索引,即位圖索引,目前已知的是 Oracle 數據庫支持,當表中的數據只有幾種值時,例如性別字段,BitMap 索引就是最佳的選擇了。BitMap 索引不適合高併發的聯機事務處理系統,而適合於併發較少,且統計運算較多的系統。

4、密集索引和稀疏索引的區別?

定義
密集索引 密集索引文件中的每個搜索碼值都對應一個索引值。即葉子節點不僅僅保存鍵位信息、該行數據的地址,還保存了位於同一行記錄裏的其他列的信息,由於密集索引決定了表的物理排列順序,一個表只能有一個物理排列順序,所以一個表只能創建一個密集索引。
稀疏索引 稀疏索引文件只爲搜索碼的某些值建立索引項。即葉子節點僅保存了鍵位信息、該行數據的地址。

InnoDB 主鍵索引、唯一索引、普通索引均屬於稀疏索引。

InnoDB 有且僅有一個密集索引,這個密集索引的選取規則:

  • 若一個主鍵被定義,該主鍵則作爲密集索引;
  • 若沒有主鍵被定義,該表的第一個唯一非空索引則作爲密集索引;
  • 若不滿足以上條件,InnoDB 內部會生成一個隱藏主鍵(密集索引);
  • 在 InnoDB 中,非主鍵索引即是稀疏索引,存儲了相關鍵位信息和該行數據的地址,包含兩次查找,而密集索引只需要一次查找。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章