MySQL與TiDB基礎知識類比

溫故而知新 能夠爲師矣node

1、存儲模型

MySQL

Each tablespace consists of database pages with a default size of 16KB. The pages are grouped into extents of size 1MB (64 consecutive pages). The 「files」 inside a tablespace are called segments in InnoDB. Two segments are allocated for each index in InnoDB. One is for nonleaf nodes of the B-tree, the other is for the leaf nodes. Keeping the leaf nodes contiguous on disk enables better sequential I/O operations, because these leaf nodes contain the actual table data.sql

  • 表空間Tablespace(ibd文件)
  • 段Segment(一個索引2個段)
  • 區Extent(1MB):64個Page
  • 頁Page(16KB):磁盤管理的最小單位

從示意圖能夠清晰的瞭解到MySQL的行數據Row都是存儲到數據頁Page上,每一個數據頁的大小爲16KB。而後64個數據頁進而組成一個區Extent,區又是段segment組成元素,一個索引擁有兩個段,其中leaf node seagment存儲着邏輯上的行數據(主鍵索引),非主鍵索引存儲的是主鍵ID。數據庫

InnoDB使用了B+樹的索引模型。B+樹爲了維護索引的有序性,在插入新值的時候須要作必須的維護。若是在表尾插入,只需在記錄後面增長,要是增長的行在表中間,就須要挪動位置給插入的行騰出空間。更糟糕的是帶插入的數據頁Page已經滿了16KB,這時須要新申請一個新的數據頁,而後將部分數據挪過去。這個過程成爲也分裂。緩存

既然存在頁分裂,那麼固然也會存在頁合併。將利用率低的Page頁進行合併,頁分裂的逆過程。bash

不論是頁的分裂仍是合併,都會引發性能的損失。這裏就須要考慮主鍵是否必需要自增?主鍵自增的模式下,每次插入的新紀錄都是追加操做,都不涉及其它記錄的挪動,不會觸發葉子節點的分裂。服務器

TiDB

TiDB的存儲與SQL模型是沒有關係的,TiKV 沒有選擇直接向磁盤上寫數據,而是把數據保存在 RocksDB 中,具體的數據落地由 RocksDB 負責。全部能夠簡化TiKV的存儲模型爲:網絡

  1. 這是一個巨大的 Map,也就是存儲的是 Key-Value pair
  2. 這個 Map 中的 Key-Value pair 按照 Key 的二進制順序有序,也就是咱們能夠 Seek 到某一個 Key 的位置,而後不斷的調用 Next 方法以遞增的順序獲取比這個 Key 大的 Key-Value

Regionmvc

對於一個 KV 系統,將數據分散在多臺機器上有兩種比較典型的方案:一種是按照 Key 作 Hash,根據 Hash 值選擇對應的存儲節點;另外一種是分 Range,某一段連續的 Key 都保存在一個存儲節點上。TiKV 選擇了第二種方式,將整個 Key-Value 空間分紅不少段,每一段是一系列連續的 Key,咱們將每一段叫作一個 Region,而且咱們會盡可能保持每一個 Region 中保存的數據不超過必定的大小(這個大小能夠配置,目前默認是 64mb)。每個 Region 均可以用 StartKey 到 EndKey 這樣一個左閉右開區間來描述。分佈式

儘管Region跟Page的概念很像,但須要注意的時候Region是鍵值對的存儲區,與關係型數據表沒有關係。Region做爲TiDB提供分佈式和高可用的核心工做單元,將數據劃分紅 Region 後會作兩件事:ide

  • 以 Region 爲單位,將數據分散在集羣中全部的節點上,而且儘可能保證每一個節點上服務的 Region 數量差很少
  • 以 Region 爲單位作 Raft 的複製和成員管理

那麼關係型的表是如何在TiKV中進行映射呢?定義個表t1,主鍵爲id,惟一索引name和普通索引age。

CREATE TABLE t1 {
	id BIGINT PRIMARY KEY,
	name VARCHAR(1024),
	age BIGINT,
	content BLOB,
	UNIQUE(name),
	INDEX(age),
};
-- 向t1中插入兩條數據
insert into t1 values(1, 「a」, 10, 「hello」);
insert into t1 values(2, 「b」, 12, 「world」);
複製代碼

上面的兩條數據就會映射成下面的鍵值對存儲到TiKV的Map中:

PK
t_11_1 -> (1, 「a」, 10, 「hello」)
t_11_2 -> (2, 「b」, 12, 「world」)

Unique Name
i_12_a -> 1
i_12_b -> 2

Index Age
i_13_10_1 -> nil
i_13_12_2 -> nil
複製代碼

由於 PK 具備惟一性,因此能夠用 t + Table ID + PK 來惟一表示一行數據,value 就是這行數據。對於 Unique 來講,也是具備惟一性的,因此用 i + Index ID + name 來表示,而 value 則是對應的 PK。若是兩個 name 相同,就會破壞惟一性約束。當咱們使用 Unique 來查詢的時候,會先找到對應的 PK,而後再經過 PK 找到對應的數據,這裏與MySQL的回表有點相似。

對於普通的 Index 來講,不須要惟一性約束,因此使用 i + Index ID + age + PK,而 value 爲空。由於 PK 必定是惟一的,因此兩行數據即便 age 同樣,也不會衝突。當咱們使用 Index 來查詢的時候,會先 seek 到第一個大於等於 i + Index ID + age 這個 key 的數據,而後看前綴是否匹配,若是匹配,則解碼出對應的 PK,再從 PK 拿到實際的數據。

2、SQL執行過程

MySQL

TiDB

從兩個流程圖能夠不難看出SQL的被執行的流程分爲:

  1. 創建鏈接。
  2. 客戶端發送一條SQL給服務器。
  3. 服務器先檢查查詢緩存,若是命中緩存當即返回存儲在緩存的結果。不然進入下一階段。
  4. 服務器端進行SQL解析、預處理,再由優化器生成對應的執行計劃。
  5. 根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢。
  6. 將結果返回給客戶端。

那麼TiDB做爲分佈式數據庫,在SQL處理過程當中存在下面幾個難點:

  1. SQL語言自己是一門複雜的語言。
  2. SQL是一門表意的語言,只是說『要什麼數據』,而不說『如何拿數據』。
  3. 分佈式存儲引擎。須要考慮下層的數據是分片、網絡不通如何處理。

3、事務隔離

MySQL

Mysql事務實現原理

READ UNCOMMITTED

事務中能夠讀到其餘事務未提交的修改,形成髒讀。

READ COMMITTED

事務未提交的修改對其它事務是不可見的,事務只會看到被提交的修改。

REPEATABLE READ

在同一事務中讀取的數據始終是一致的,就算讀取的數據有被其它事務提交過修改。

使用讀寫鎖實現

使用mvcc實現

ERIALIZABLE 事務的執行按照串行執行。

引用表格總結一下始終事務隔離

TiDB

TiKV 的事務採用的是 Percolator 模型。TiKV 的事務採用樂觀鎖,事務的執行過程當中,不會檢測寫寫衝突,只有在提交過程當中,纔會作衝突檢測,衝突的雙方中比較早完成提交的會寫入成功,另外一方會嘗試從新執行整個事務。TiKV也實現了MVCC。TiKV 的 MVCC 實現是經過在 Key 後面添加 Version 來實現,簡單來講,沒有 MVCC 以前,能夠把 TiKV 看作這樣的:

Key1 -> Value
Key2 -> Value
……
KeyN -> Value
複製代碼

有了 MVCC 以後,TiKV 的 Key 排列是這樣的:

Key1-Version3 -> Value
Key1-Version2 -> Value
Key1-Version1 -> Value
……
Key2-Version4 -> Value
Key2-Version3 -> Value
Key2-Version2 -> Value
Key2-Version1 -> Value
……
KeyN-Version2 -> Value
KeyN-Version1 -> Value
……
複製代碼

4、索引

MySQL

最左前綴原則

因爲覆蓋索引(查詢中索引已經覆蓋了查詢的需求,能夠直接提供結果不須要回表,稱之爲:覆蓋索引)能夠顯著的優化查詢性能,而且索引的維護也是有代價的。因此如何權衡就是個問題。

最左前綴原則:即最左優先,在檢索數據時從聯合索引的最左邊開始匹配,也能夠是字符串索引的最左邊的字符開始匹配。在創建聯合索引時將高頻的字段放置左側。

索引下推:(index condition pushdown) 索引遍歷過程當中,對索引中包含的字段先作判斷,直接過濾掉減小回表。

TiDB

這裏留個坑,後面去填。 索引範圍計算簡介

相關文章
相關標籤/搜索