Kylin5 对接 Starrocks 数据源

背景

Apache Kylin5 是一个 OLAP 分析引擎,他通过构建引擎来读取数据源数据生成预计算索引数据。

他通过查询引擎来查询预计算好的索引数据,也可以通过 Pushdown 能力,将查询下压给数据源引擎


StarRocks 是一款 MPP 架构的分析型数据库,可以高效支持大数据量级的多维分析、实时分析、高并发分析等多种数据分析场景。

痛点

公司内部使用的两款查询引擎如下

  • StarRocks:查询性能出色,采用的向量化、CBO 等能力让其查询速度更上一层。

    • 优点
      • 查询优化手段很多:向量化、CBO、物化视图等。
      • 数据量小时,无论是聚合还是明细查询都快。
    • 缺点
      • 大多数查询都是现算,导致查询并发不高。
      • 数据量很大时,复杂查询比较吃力。
  • Kylin:预计算之后的查询速度快,但是 Ad-Hoc 分析是其短板。

    • 优点
      • 预先定义好维度、度量的查询可以达到毫秒级查询。
      • 数据量很大时,命中索引的复杂查询也可以保证秒级返回。
      • 由于不需要现算,使得查询并发高。
    • 缺点
      • 需要熟悉业务的人员预先定义模型、维度、度量、索引,才能实现查询加速。
      • Ad-Hoc 即席查询 无法命中索引的,查询速度由数据量决定,速度无法保障。

为了统一的查询入口,我们将各有所长的 Kylin 和 StarRocks 融合在一起,会碰撞出怎样的火花呢?

如何融合 - 谁融合谁?

Kylin5 作为 StarRocks 的数据源

StarRocks 通过 Catalog 管理和查询内部数据与外部数据。
Kylin 是支持 JDBC 查询的。

抱着试一试的心态,修改了 StarRocks FE 的代码,让其 FE 端能识别 Kylin 的 JDBC 连接串。

结果是失败了,虽然成功连接上 Kylin5 并发起查询,但是无法获取查询结果返回给 Starrocks。

初步定位问题出自 BE 端,后续尝试研究一下 BE 的 C++ 代码,解决无法获取数据的问题。

StarRocks 作为 Kylin5 的数据源

StarRocks 作为 Kylin5 的数据源,需要满足 Kylin5 的以下三个功能点

  1. StarRocks 元数据获取
  2. StarRocks 支持 Spark 读取数据
  3. StarRocks 支持 Kylin5 的 PushDown 查询

构建流程

Kylin5 构建 StarRock 流程图

主要改动点

  • Spark 由原先读取 Hive 数据源,修改为通过 Spark-StarRocks-Connector 并行读取 StarRocks 数据。
  • Kylin5 构建时取数的分区过滤条件,下推到 StarRocks 进行过滤。
如不进行下推,则会进行全表扫描后再过滤分区。
测试代码

查询流程

Kylin5 对接 StarRocks 查询流程图

查询流程基本与原先一致
但是为了适配 StarRocks 的语法,对 Kylin5 做了一些小修改。

  • Kylin5 查询 SQL 解析失败时,如果是以下几种情况,则直接将 SQL 下推到 StarRocks 进行查询。
    • 表不存在
    • 函数不存在
    • 数据不存在
    • Group By column Index
      这么做的主要原因是
  • Kylin5 使用的 Calcite 版本比较低,很多函数与主流查询引擎有些许差异。
  • 当遇到 Calcite 无法解析的函数时,则会直接失败。
测试代码

融合效果 - 融合后怎么进行查询?

既然选择将 StarRocks 作为 Kylin5 的数据源。可以得到一个基本的架构

  • Kylin5 只构建 StarRocks 中常用的聚合查询索引,用于回答聚合查询
  • StarRocks 作为 Kylin5 的 PushDown 引擎,用于回答即席查询和明细查询
我们又回到这张图,可以根据是否命中索引,来区分 Kylin5 索引查询 StarRocks 查询。
查询流程图

查询性能

可以发现,两个引擎是互补的关系,将 StarRocks 查起来比较费劲的 SQL 放到 Kylin5 上进行预计算做到能力分摊,合适的 SQL 分发到合适的引擎上进行查询。

  • 数据量小的情况下,其实 Kylin5 预计算并没有特别突出的优势
  • 数据量大,并且计算复杂(Count Distinct)Kylin5 预计算的优势开始凸显
  • Kylin5 中没有索引可以回答查询时,会主动将查询 PushDownStarRocks 中进行快速查询

在查询历史中,可以看到查询的回答方式,是索引回答还是 StarRocks 回答。

构建性能

StarRocks 单分区 7 亿条数据 共 55GB。

Kylin5 构建 2 个索引需要 15 分钟。

遇到的问题 - 踩了哪些坑?

后续软件版本更新若解决了这些问题,请忽略

1.  数据类型转换异常

注:2023-08-11 对接时遇到该问题,各组件版本信息如下
Spark:3.2.0
Connector: 1.1.0
StarRocks:2.5.1

问题描述

在使用 Starrocks-Spark-Connector-1.1.0 版本时,读取 Date 类型的字段转化成 Spark DateType 时出现了问题。

Connector 从 Starrocks 中读取到的数据 dt 字段是 String 类型,但是其 schema 又是 DateType,所以报错。

给社区开了个 ISSUE 详细信息可以进入下方链接查看。

数据类型转换异常 · Issue #77 · StarRocks/starrocks-connector-for-apache-spark

解决方法

社区的伙伴经过尝试无法复现,而我在将 Starrocks-Spark-Connector-1.1.0 降级到 1.0.0 ,就避开了此问题。

由此不再深究。因为 1.0.0 版本会将 Date 类型用 StringType 进行读取

2. Spark 读取 StarRocks 数据 Timeout

注:2023-08-30 对接时遇到该问题,各组件版本信息如下
Spark:3.2.0
Connector: 1.0.0
StarRocks [问题版本]:2.5.1
StarRocks [修复版本]:2.5.8 +

问题描述

具体细节不是特别清楚,感兴趣的小伙伴可以查看下方 PR 链接

[BugFix] Cancel fragment instance not query when close external scanner by wyb · Pull Request #20264

解决方法

此 BUG 已在 2.5.8+ 版本修复,故将 StarRocks 升级到 2.5.8 版本后,不再出现该报错。

3. Spark 读取 StarRocks 数据MemoryScratchSinkOperator

注:2023-08-31 对接时遇到该问题,各组件版本信息如下
Spark:3.2.0
Connector: 1.0.0
StarRocks [问题版本]:2.5.8
StarRocks [修复版本]:暂无,等待社区发布最新版本

问题描述

BE 内存统计时,错误的将输出的结果集的内存占用统计进了查询内存中,导致查询内存统计异常膨胀,超出阈值后被 BE Kill。

本不该被统计的内存,结果被错误的统计了,由此导致的查询被意外 Kill。

解决方法

目前暂无临时解决方法,社区已修复需等待社区发布最新版本。

[BugFix] Fix them mem statistics bug of MemoryScratchSink by trueeyu · Pull Request #30751 · StarRoc

总结

通过本次技术调研,确认了以Kylin5为基础,融合多种数据源进行联合查询的可行性。也确定了统一数据查询入口的可行性。

如应用到生产中,可以解决以下问题

  • 统一查询入口,查询入口众多导致业务人员搞不清楚到底该去哪里查,哪里查询最合适。
  • 不同查询引擎之间的负载均衡,查询引擎之间的互补,有效的分摊了查询引擎的压力。

除了 StarRocks,将来还可以继续探索将MySQL、PostgreSQL等其他数据库接入Kylin5,作为Kylin5的数据源。