做者: 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 的概要,读者对此有个概念便可。后续咱们将推出该模块相关的更多更深的源码细节分析,欢迎你们继续阅读并给出建设性的改进意见。