做者: Shirlybash
本文將簡要介紹 TiKV Coprocessor 的基本原理,面向想要了解 TiKV 數據讀取執行過程的同窗,同時也面向想對該模塊貢獻代碼的同窗。閱讀本文前,建議讀者對 TiDB 總體架構有所瞭解,先閱讀三篇文章瞭解 TiDB 技術內幕:說存儲、說計算、談調度。網絡
熟悉 TiDB 總體框架 的同窗可能記得,TiDB 是無狀態的,數據存儲在 TiKV 層。當 TiDB 在收到一個來自客戶端的查詢請求時,會向 TiKV 獲取具體的數據信息。那麼一個讀請求最樸素的處理過程以下:架構
首先須要確定的是這種方式當然能解決問題,可是性能如何呢?咱們來一塊兒分析一下:框架
看到以上問題後,聰明如你,可能很容易就想到,能不能讓 TiKV 把本身負責的那部分數據作一次計算,再返回給 TiDB 呢?異步
有何不可呢?函數
TiKV 讀取數據並計算的模塊,咱們定義爲 Coprocessor,該概念靈感來自於 HBase,目前在 TiDB 中的實現相似於 HBase 中的 Coprocessor 的 Endpoint 部分,也可類比 MySQL 存儲過程。性能
有了 Coprocessor 後,從宏觀看一個讀請求是如何下發到 TiKV 的呢?如下面的請求爲例:優化
如圖,以上查詢語句在 TiDB 中處理以下:spa
TiKV Coprocessor 處理的讀請求目前主要分類三種:線程
那麼 TiKV 在收到 Coprocessor 請求後,什麼時候區分這三種請求的呢?
請求到了 TiKV 層,處理過程以下:
目前 Coprocessor 支持的三種接口中,後面兩種接口相對比較簡單,而 DAG 是裏面最複雜也是最經常使用的,因此本文後續將重點介紹 DAG 類請求。
DAG 顧名思義,是由一系列算子組成的有向無環圖,算子在代碼中稱爲 Executors。
目前 DAG 請求主要實現了兩種計算模型:
在目前的 TiKV master 上,處於火山模型向向量化模型的過分階段,於是兩種計算模型同時存在。TiKV 收到請求時,會優先檢測是否可走向量化模型,若部分功能在向量化模型中沒有實現,則走舊的計算模型,具體處理邏輯流程以下:
相關代碼在:src/coprocessor/dag/mod.rs
。
由於火山模型已在被棄用中,因此下文咱們只講向量化計算模型。
在向量化計算模型中,全部算子都實現了 BatchExecutor
接口,其主要定義了一個 get_batch
的函數:
pub trait BatchExecutor: Send {
fn next_batch(&mut self, scan_rows: usize) -> BatchExecuteResult;
}
pub struct BatchExecuteResult {
pub physical_columns: LazyBatchColumnVec,
pub logical_rows: Vec<usize>,
pub is_drained: Result<bool, Error>,
...
}
複製代碼
參數說明:
next_batch
中 scan_rows
由上層控制,因爲掃的數據過多會慢,所以該數字從 32 倍增到 1024。
返回值 BatchExecuteResult
中,因爲返回了一批空數據不表明全部數據都處理完畢了,例如可能只是全被過濾,於是使用單獨字段表示全部數據處理完畢。
目前 TiKV 支持的算子主要有如下幾類。
定義:根據指定主鍵範圍掃表數據,並過濾出一部分列返回。它只會做爲最底層算子出現,從底層 KV 獲取數據。
源碼路徑:components/tidb_query/src/batch/executors/table_scan_executor.rs
案例:select col from t
定義:根據指定索引返回掃索引數據,並過濾出一部分索引列返回。它只會做爲最底層算子出現,從底層 KV 獲取數據。
源碼路徑:components/tidb_query/src/batch/executors/index_scan_executor.rs
案例:select index from t
定義:對底層算子的結果按照過濾條件進行過濾,其中這些條件由多個表達式組成。
源碼路徑:components/tidb_query/src/batch/executors/selection_executor.rs
案例:select col from t where a+b=10
定義:從底層算子吐出的數據中,限定返回若干行。
源碼路徑:components/tidb_query/src/batch/executors/limit_executor.rs
案例:select col from t limit 10
定義:按照給定表達式進行排序後,取出前若干行數據。
源碼路徑:components/tidb_query/src/batch/executors/top_n_executor.rs
案例:select col from t order by a+1 limit 10
定義:按照給定表達式進行分組、聚合。
源碼路徑:components/tidb_query/src/batch/executors/*_aggr_executor.rs
案例: select count(1) from t group by score + 1
綜上,各個算子之間能夠按照如下方式任意組合,以下圖所示:
案例:select count(1) from t where age>10
因爲篇幅緣由,本文只是講了一些 Coprocessor 的概要,讀者對此有個概念便可。後續咱們將推出該模塊相關的更多更深的源碼細節分析,歡迎你們繼續閱讀並給出建設性的改進意見。