MySQL 的經常使用引擎

1. InnoDB

InnoDB 的存儲文件有兩個,後綴名分別是 .frm 和 .idb,其中 .frm 是表的定義文件,而 idb 是數據文件。node

InnoDB 中存在表鎖和行鎖,不過行鎖是在命中索引的狀況下才會起做用。算法

InnoDB 支持事務,且支持四種隔離級別(讀未提交、讀已提交、可重複讀、串行化),默認的爲可重複讀;而在 Oracle 數據庫中,只支持串行化級別和讀已提交這兩種級別,其中默認的爲讀已提交級別。數據庫

2. Myisam

Myisam 的存儲文件有三個,後綴名分別是 .frm、.MYD、MYI,其中 .frm 是表的定義文件,.MYD 是數據文件,.MYI 是索引文件。緩存

Myisam 只支持表鎖,且不支持事務。Myisam 因爲有單獨的索引文件,在讀取數據方面的性能很高 。數據結構

3. 存儲結構

InnoDB 和 Myisam 都是用 B+Tree 來存儲數據的。ide

MySQL 的數據、索引存儲結構

1. 數據存儲的原理(硬盤)

信息存儲在硬盤裏,硬盤是由不少的盤片組成,經過盤片表面的磁性物質來存儲數據。性能

把盤片放在顯微鏡下放大,能夠看到盤片表面是凹凸不平的,凸起的地方被磁化,表明數字 1,凹的地方沒有被磁化,表明數字 0,所以硬盤能夠經過二進制的形式來存儲表示文字、圖片等的信息。優化

硬盤有不少種,可是都是由盤片、磁頭、盤片主軸、控制電機、磁頭控制器、數據轉換器、接口、緩存等幾個部分組成。spa

全部的盤片都固定在一個旋轉軸上,這個軸即盤片主軸。操作系統

全部的盤片之間是絕對平行的,在每一個盤片的盤面上都有一個磁頭,磁頭與盤片之間的距離比頭髮絲的直徑還小。

全部的磁頭連在一個磁頭控制器上,由磁頭控制器負責各個磁頭的運動,磁頭可沿盤片的半徑方向移動,其實是斜切運動,每一個磁頭同一時刻必須是同軸的,即從正上方往下看,全部磁頭任什麼時候候都是重疊的。

因爲技術的發展,目前已經有多磁頭獨立技術了,在此不考慮此種狀況。

盤片以每分鐘數千轉到上萬轉的速度在高速運轉,這樣磁頭就能對盤片上的指定位置進行數據的讀寫操做。

因爲硬盤是高精密設備,塵埃是其大敵,因此必須徹底密封。

2. 數據讀寫的原理

硬盤在邏輯上被劃分爲磁道、柱面以及扇區。

磁頭靠近主軸接觸的表面,即線速度最小的地方,是一個特殊的區域,它不存聽任何數據,稱爲啓停區或者着陸區,啓停區外就是數據區。

在最外圈,離主軸最遠的地方是 「0」 磁道,硬盤數據的存放就是從最外圈開始的。

在硬盤中還有一個叫 「0」 磁道檢測器的構件,它是用來完成硬盤的初始定位。

盤面

硬盤的盤片通常用鋁合金材料作基片,硬盤的每個盤片都有上下兩個盤面,通常每一個盤面都會獲得利用,均可以存儲數據,成爲有效盤面,也有極個別的硬盤盤面數爲單數。

每個這樣的有效盤面都有一個盤面號,按順序從上至下從 0 開始編號。

在硬盤系統中,盤面號又叫磁頭號,由於每個有效盤面都有一個對應的讀寫磁頭,硬盤的盤片組在 2-14 片不等,一般有 2-3 個盤片。

磁道

磁盤在格式化時被劃分紅許多同心圓,這些同心圓軌跡叫作磁道。

磁道從外向內從 0 開始順序編號,硬盤的每個盤面有 300-1024 個磁道,新式大容量硬盤每面的磁道數更多,信息以脈衝串的形式記錄在這些軌跡中,這些同心圓不是連續記錄數據,而是被劃分紅一段段的圓弧。

這些圓弧的角速度同樣,因爲徑向長度不同,因此線速度也不同,外圈的線速度較內圈的線速度大,即一樣的轉速度下,外圈在一樣時間段裏,劃過的圓弧長度要比內圈劃過的圓弧長度大。

每段圓弧叫作一個扇區,扇區從 1 開始編號,每一個扇區中的數據做爲一個單元同時讀出或寫入。

磁道是看不見的,只是盤面上以特殊形式磁化了的一些磁化區,在磁盤格式化時就已規劃完畢。

柱面

全部盤面上的同一磁道構成一個圓柱,一般稱做柱面。

每一個圓柱上的磁頭由上而下從 0 開始編號,數據的讀 / 寫按柱面進行,即磁頭讀 / 寫數據時首先在同一柱面內從 0 磁頭開始進行操做,依次向下在同一柱面的不一樣盤面即磁頭上進行操做。

只有在同一柱面全部的磁頭所有讀 / 寫完畢後磁頭才轉移到下一柱面(同心圓再往裏的柱面),由於選取磁頭只須要經過電子切換便可,而選取柱面則必須機械切換,電子切換至關快,比在機械上的磁頭向鄰近磁道移動快得多。

因此,數據的讀 / 寫按柱面進行,而不按盤面進行,也就是說,一個磁道寫滿數據後,就在同一柱面的下一個盤面來寫,一個柱面寫滿後,才移到下一個扇區開始寫數據,讀數據也按照這種方式進行,這樣就提升了硬盤的讀 / 寫效率。

扇區

操做系統以扇區形式將信息存儲在硬盤上,每一個扇區包括 512 個字節的數據和一些其餘信息,一個扇區有兩個主要部分:存儲數據地點的標識符和存儲數據的數據段。

標識符就是扇區頭標,包括組成扇區三維地址的三個數字:盤面號,柱面號,扇區號(塊號)。

數據段可分爲數據和保護數據的糾錯碼(ECC)。在初始準備期間,計算機用 512 個虛擬信息字節(實際數據的存放地)和與這些虛擬信息字節相應的 ECC 數字填入這個部分。

3. 訪盤請求完成過程

1)肯定磁盤地址(柱面號,磁頭號,扇區號),內存地址(源 / 目):

當須要從磁盤讀取數據的時候,系統會將數據的邏輯地址傳遞個磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即肯定要讀的數據在哪一個磁道,哪一個扇區。

2)爲了讀取這個扇區的數據,須要將磁頭放到這個扇區上方,爲了實現這一點:

 

  • A. 首先必須找到柱面,即磁頭須要移動對準相應磁道,這個過程叫作尋道,所耗費時間叫作尋道時間。
  • B. 而後目標扇區旋轉到磁頭下,即磁盤旋轉將目標扇區旋轉到磁頭下,這個過程耗費的時間叫作旋轉時間。

 

3)即一次訪盤請求(讀 / 寫)完成過程由三個動做組成:

 

  • A. 尋道(時間):磁頭移動定位到指定磁道。
  • B. 旋轉延遲(時間):等待指定扇區從磁頭下旋轉通過。
  • C. 數據傳輸(時間):數據在磁盤與內存之間的實際傳輸。

 

4. 磁盤的讀寫原理

系統將文件存儲到磁盤上時,按柱面、磁頭、扇區的方式進行,即最早是第 1 磁道的第一磁頭下的全部扇區,而後是同一柱面的下一個磁頭……

一個柱面存儲滿後就推動到下一個柱面,直到把文件內容所有寫入磁盤。

系統也以相同的順序讀出數據,讀出數據時經過告訴磁盤控制器要讀出扇區所在柱面號、磁頭號和扇區號(物理地址的三個組成部分)進行。

5. 減小 I/O 的預讀原理

因爲存儲介質的特性,磁盤自己存取就比主存慢不少,再加上機械運動耗費的時間,磁盤的存取速度每每是主存的幾百分之一。

所以,爲了提升效率,要儘可能減小磁盤的 I/O。

磁盤每每不是嚴格地按需讀取,而是每次都會預讀,即便只須要一個字節,磁盤也會從這個位置開始,順序向後讀取必定長度的數據放入內存。

這樣作的理論依據是計算機科學中著名的局部性原理:

 

  1. 當一個數據被用到時,其附近的數據通常來講也會被立刻使用。
  2. 程序運行期間所須要的數據一般比較集中。
  3. 因爲磁盤順序讀取的效率很高(不須要尋道時間,只須要不多的旋轉時間),所以對於具備局部性的程序來講,預讀能夠提升 I/O 效率。

 

預讀的長度通常爲頁(Page)的整數倍。頁是計算機管理存儲器的邏輯塊,硬件及操做系統每每將主存和磁盤存儲分割爲連續的大小相等的塊。

每一個存儲塊稱爲一頁(在許多操做系統中,頁的大小一般爲 4k),主存和磁盤以頁爲單位交換數據,當程序要讀取的數據不在主存中時,會觸發一個缺頁異常。

此時系統會向磁盤發出讀盤信息,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁的數據載入內存中,而後異常返回,程序繼續運行。

6. MySQL 的索引

索引是一種用來實現 MySQL 高效獲取數據的數據結構。

咱們一般所說的在某個字段上建索引,意思就是讓 MySQL 對該字段以索引這種數據結構來存儲,而後查找的時候就有對應的查找算法。

建索引的根本目的是爲了查找的優化,特別是當數據很龐大的時候,通常的查找算法有順序查找、折半查找、快速查找等。

可是每種查找算法都只能應用於特定的數據結構之上,例如順序查找依賴於順序結構,折半查找經過二叉查找樹或紅黑樹實現二分搜索。所以在數據以外,數據庫系統還維護着知足特定查找算法的數據結構。

這些數據結構以某種方式引用數據,這樣就能夠在這些數據結構上實現高級查找算法,這種數據結構就是索引。

7. MySQL 的 B+Tree

目前大多數數據庫系統及文件系統都採用 B-Tree 或其變種 B+Tree 做爲索引結構。

B+ 樹索引是 B+ 樹在數據庫中的一種實現,是最多見也是數據庫中使用最爲頻繁的一種索引。B+ 樹中的 B 表明平衡,而不是二叉。

由於 B+ 樹是從最先的平衡二叉樹演化而來的。B+ 樹是由二叉查找樹、平衡二叉樹(AVLTree)和平衡多路查找樹(B-Tree)逐步優化而來。

二叉查找樹:左子樹的鍵值小於根的鍵值,右子樹的鍵值大於根的鍵值。

AVL 樹:平衡二叉樹(AVL 樹)在符合二叉查找樹的條件下,還知足任何節點的兩個子樹的高度最大差爲 1。

平衡多路查找樹(B-Tree):爲磁盤等外存儲設備設計的一種平衡查找樹。

系統從磁盤讀取數據到內存時是以磁盤塊(block)爲基本單位的,位於同一磁盤塊中的數據會被一次性讀取出來,而不是按需讀取。

InnoDB 存儲引擎使用頁做爲數據讀取單位,頁是其磁盤管理的最小單位,默認 page 大小是 16k。

系統的一個磁盤塊的存儲空間每每沒有這麼大,所以 InnoDB 每次申請磁盤空間時都會是若干地址連續磁盤塊來達到頁的大小 16KB。

InnDB 在把磁盤數據讀入到磁盤時會以頁爲基本單位,在查詢數據時若是一個頁中的每條數據都能助於定位數據記錄的位置,這將會減小磁盤 I/O 的次數,提升查詢效率。

B-Tree 結構的數據可讓系統高效的找到數據所在的磁盤塊。

爲了描述 B-Tree,首先定義一條數據記錄爲一個二元組 [key, data],key 爲記錄的鍵值,對於不一樣數據記錄,key 是互不相同的;data 爲數據記錄除 key 外的數據。

那麼 B-Tree 是知足下列條件的數據結構:

  1. d 爲大於 1 的一個正整數,稱爲 B-Tree 的度。
  2. h 爲一個正整數,稱爲 B-Tree 的高度。
  3. 每一個非葉子節點由 n-1 個 key 和 n 個指針組成,其中 d<=n<=2d。
  4. 每一個葉子節點最少包含一個 key 和兩個指針,最多包含 2d-1 個 key 和 2d 個指針,葉節點的指針均爲 null 。
  5. 全部葉節點具備相同的深度,等於樹高 h。
  6. key 和指針互相間隔,節點兩端是指針。
  7. 一個節點中的 key 從左到右非遞減排列。
  8. 全部節點組成樹結構。
  9. 每一個指針要麼爲 null,要麼指向另一個節點。
  10. 若是某個指針在節點 node 最左邊且不爲 null,則其指向節點的全部 key 小於 v(key1),其中 v(key1) 爲 node 的第一個 key 的值。
  11. 若是某個指針在節點 node 最右邊且不爲 null,則其指向節點的全部 key 大於 v(keym),其中 v(keym) 爲 node 的最後一個 key 的值。
  12. 若是某個指針在節點 node 的左右相鄰 key 分別是 keyi 和 keyi+1 且不爲 null,則其指向節點的全部 key 小於 v(keyi+1) 且大於 v(keyi)。

B-Tree 中的每一個節點根據實際狀況能夠包含大量的關鍵字信息和分支,例:

每一個節點佔用一個盤塊的磁盤空間,一個節點上有兩個升序排序的關鍵字和三個指向子樹根節點的指針,指針存儲的是子節點所在磁盤塊的地址。

兩個關鍵詞劃分紅的三個範圍域對應三個指針指向的子樹的數據的範圍域。

以根節點爲例,關鍵字爲 17 和 35,P1 指針指向的子樹的數據範圍爲小於 17,P2 指針指向的子樹的數據範圍爲 17~35,P3 指針指向的子樹的數據範圍爲大於 35。

模擬查找關鍵字 29 的過程:

  1. 根據根節點找到磁盤塊 1,讀入內存。【磁盤 I/O 操做第 1 次】
  2. 比較關鍵字 29 在區間(17,35),找到磁盤塊 1 的指針 P2。
  3. 根據 P2 指針找到磁盤塊 3,讀入內存。【磁盤 I/O 操做第 2 次】
  4. 比較關鍵字 29 在區間(26,30),找到磁盤塊 3 的指針 P2。
  5. 根據 P2 指針找到磁盤塊 8,讀入內存。【磁盤 I/O 操做第 3 次】
  6. 在磁盤塊 8 中的關鍵字列表中找到關鍵字 29。

MySQL 的 InnoDB 存儲引擎在設計時是將根節點常駐內存的,所以力求達到樹的深度不超過 3,也就是說 I/O 不須要超過 3 次。

分析上面過程,發現須要 3 次磁盤 I/O 操做,和 3 次內存查找操做。因爲內存中的關鍵字是一個有序表結構,能夠利用二分法查找提升效率。

而 3 次磁盤 I/O 操做是影響整個 B-Tree 查找效率的決定因素。

B-Tree 相對於 AVLTree 縮減了節點個數,使每次磁盤 I/O 取到內存的數據都發揮了做用,從而提升了查詢效率。

B+Tree 是在 B-Tree 基礎上的一種優化,使其更適合實現外存儲索引結構,InnoDB 存儲引擎就是用 B+Tree 實現其索引結構。

在 B-Tree 中,每一個節點中有 key,也有 data,而每個頁的存儲空間是有限的,若是 data 數據較大時將會致使每一個節點(即一個頁)能存儲的 key 的數量很小。

當存儲的數據量很大時一樣會致使 B-Tree 的深度較大,增大查詢時的磁盤 I/O 次數,進而影響查詢效率。

在 B+Tree 中,全部數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲 key 值信息,這樣能夠大大加大每一個節點存儲的 key 值數量,下降 B+Tree 的高度。

B+Tree 在 B-Tree 的基礎上有兩點變化:

  1. 數據是存在葉子節點中的;
  2. 數據節點之間是有指針指向的

因爲 B+Tree 的非葉子節點只存儲鍵值信息,假設每一個磁盤塊能存儲 4 個鍵值及指針信息,則變成 B+Tree 後其結構以下圖所示:

一般在 B+Tree 上有兩個頭指針,一個指向根節點,另外一個指向關鍵字最小的葉子節點,並且全部葉子節點(即數據節點)之間是一種鏈式環結構。

所以能夠對 B+Tree 進行兩種查找運算:一種是對於主鍵的範圍查找和分頁查找,另外一種是從根節點開始,進行隨機查找。

8. Myisam 中的 B+Tree

Myisam 引擎也是採用的 B+Tree 結構來做爲索引結構。

因爲 Myisam 中的索引和數據分別存放在不一樣的文件,因此在索引樹中的葉子節點中存的數據是該索引對應的數據記錄的地址,因爲數據與索引不在一塊兒,因此 Myisam 是非聚簇索引。

 

9. InnoDB 中的 B+Tree

InnoDB 是以 ID 爲索引的數據存儲。

採用 InnoDB 引擎的數據存儲文件有兩個,一個定義文件,一個是數據文件。

InnoDB 經過 B+Tree 結構對 ID 建索引,而後在葉子節點中存儲記錄。

 

若建索引的字段不是主鍵 ID,則對該字段建索引,而後在葉子節點中存儲的是該記錄的主鍵,而後經過主鍵索引找到對應的記錄。

相關文章
相關標籤/搜索