Skip to content

Instantly share code, notes, and snippets.

@guo-shaoge
Last active October 23, 2022 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guo-shaoge/e384ea0e06a6508b241dae8877996a6f to your computer and use it in GitHub Desktop.
Save guo-shaoge/e384ea0e06a6508b241dae8877996a6f to your computer and use it in GitHub Desktop.
TiDB Hackathon 2022 RFC

TiDB Unified Execution Engine

code:

  1. https://github.com/guo-shaoge/velox/tree/gjt_tidb_velox
  2. https://github.com/guo-shaoge/tidb/tree/gjt_tidb_velox

小灰灰yyds 团队

项目介绍

借助 Velox,为 TiDB 实现一套统一的执行引擎

背景&动机

随着 TiDB 组件不断丰富,SQL 执行器的代码也在不断重复,主要包括:

  1. TiDB 本身的执行引擎
  2. TiKV 下推的执行逻辑
  3. TiFlash 下推的执行逻辑
  4. TiDB 内部 unistore 也带有一个执行器

会遇到以下问题:

  1. 维护代价:各个组件的执行器代码分布在不同 repo ,由不同语言实现,实现逻辑差异大,维护代价很高,往往相同的 bug 有可能要修复好几次
  2. 兼容性:繁琐的表达式逻辑需要在不同组件实现多次,由于不同语言使用的库不同,有些数字计算表达式的结果甚至不能保证一样
  3. 性能:各个引擎之间性能没有统一的标准,性能优化工作也必须分开进行

Velox 是由 Facebook 开源的一套向量化执行引擎,可以将其嵌入到不同系统中,在 Facebook 内部已经逐步使用,替换了 Presto 以及 Spark 的引擎。 对于 TiDB 这种一个系统但是组件很多的场景也非常适用,统一引擎后有如下好处:

  1. 维护代价降低 3 倍
  2. 不用再担心实现的表达式在各个组件上结果是否一致
  3. 性能统一,一次优化,三个引擎都能受益

项目设计

将 Velox 整合进 TiDB 主要涉及三块:

  1. PlanConvertor: 用于将 TiDB plan 转为 Velox 可以理解的 Substrait PB 格式
  2. ChunkConvertor: 将 Chunk Velox 内部的 Vector 格式,用于给 Velox 的 TableScan/Exchange 提供数据,供上层算子计算
  3. TiDBDataSource: 负责不断将格式转换后的 Vector 不断吐给 Velox

下面只列出 TiDB+Velox 的模块图,TiDB, TiKV 以及 TiFlash 内部虽然实现逻辑不同,但是基本都只需要上面三个逻辑就能将 Velox 整合(TiFlash 的 DataSource 类除了要给 Velox 的 TableScan 提供数据,还需要给进行 MPP 计算的 Exchange 算子提供数据)

tidb-velox-1

PlanConvertor

Substrait 致力于给关系几何计算提供一个跨语言的序列化标准。而 Velox 接收的 plan 是可以识别 Substrait 结构的。

所以需要一个 PlanConvertor ,将 TiDB 优化器生成计划后会先将计划序列化为 Substrait 规定的 PB 结构,再将结构传递给 Velox ,Velox 内部会解析 PB 数据,并根据输入 plan 生成执行器树。

TiDBDataSource

Velox 接收外部应用传入的计算数据需要三个抽象:Split, DataSource 以及 Connector 。对应到 TiDB ,三个抽象的功能分别如下:

  1. TiDBConnectorSplit: 相当于一个 token ,Velox 的 TableScan 算子会传递给 TiDBDataSource ,用于告诉 TiDB Velox 需要读取新的数据,同时里面还会包含需要读取的是哪个 Table 的信息
  2. TiDBDataSource:获取 TiDB 输入数据的模块,Velox 通过告诉 split 告诉 TiDBDataSource 需要返回哪个表的多少行数据。然后 Velox TableScan 算子会不断调用 TiDBDataSource::next() 方法,从 TiDB 中拿到 Arrow-compatible 的批量数据,向上层算子传递,进行实际的算子计算
  3. TiDBConnector:Velox Task 在构造时会用他生成新的 TiDBDataSource

ChunkConvertor

不同的向量化执行引擎会有不同的数据表示格式,例如 TiDB/TiKV 都用内部的 Chunk 格式,TiFlash 使用 ClickHouse 自带的 Block 格式。而 Velox 采用 Arrow-compatible 的 FlatVector/RowVector... 格式。 所以在 TiDB 将数据传入 Velox 之前需要有一个 ChunkConvertor 将 Chunk 格式转为 Arrow-compatible 格式。POD 类型的 Chunk/Block 格式与 Arrow 差异不大,所以性能损失应该不会很大。

TiKV and TiFlash

TiKV 模块不需要 PlanConvertor ,因为 TiDB 下发 copr 请求时 DAGRequest 已经会转换为 Substrait PB 格式。

主要需要完成 ChunkConvertor 以及 TiKVDataSource ,基本逻辑与 TiDBDataSource 类似,只不过实际的数据源来自 RocksDB 而非从 GRPC 读取。

为了接入 Velox 到 TiFlash ,需要提供:

  1. TiFlashDataSource 供 TableScan 使用,逻辑与 TiDBDataSource 类似
  2. TiFlashExchangeSource: 为了进行 MPP 计算,还需要提供 ExchangeSource 供 Velox 的 Exchange 算子使用,Velox 提供了灵活的抽象,包括多线程共享的 ExchangeClient ,用于创建多个 ExchangeSource 。并提供 next() 接口,供上层算子调用。我们需要完成的是使用网络通信的 ExchangeSource ,负责从其他 node 获取实际数据
@guo-shaoge
Copy link
Author

tidb-velox-1

@zanmato1984
Copy link

牛啊!

@guo-shaoge
Copy link
Author

牛啊!

^V^

@SunRunAway
Copy link

强啊

@LittleFall
Copy link

tql

@youjiali1995
Copy link

tql

@aierui
Copy link

aierui commented Oct 23, 2022

牛啊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment