StarRocks最初主要的优势是性能,当时在单表查询方面与性能标杆ClickHouse不相上下,而join优化特性使其在多表关联查询场景下的性能表现要远远优于ClickHouse,替换ClickHouse自然也就成了StarRocks的第一个目标。
而StarRocks的野心不止于此,后来又进一步发展了联邦查询功能,成为Presto的性能升级替代方案。与此同时,StarRocks优良的预计算特性让其成为Druid的一种替代选择。
先看下测试数据
Star Schema Benchmark(以下简称 SSB)是学术界和工业界广泛使用的一个星型模型测试集(来源论文),通过这个测试集合可以方便的对比各种 OLAP 产品的基础性能指标。ClickHouse 通过改写 SSB,将星型模型打平转化成宽表 (flat table),改造成了一个单表测试 benchmark(参考链接)。本报告记录了 StarRocks、ClickHouse 和 Apache Druid 在 SSB 单表数据集上的性能对比结果,测试结论如下:
ClickHouse 是一个真正的列式数据库管理系统(DBMS)。
在 ClickHouse 中,数据始终是按列存储的,包括矢量(向量或列块)执行的过程。只要有可能,操作都是基于矢量进行分派的,而不是单个的值,这被称为?矢量化查询执行?(SIMD),它有利于降低实际的数据处理开销。
这个想法并不新鲜,其可以追溯到 APL 编程语言及其后代:A +、J、K 和 Q。矢量编程被大量用于科学数据处理中。即使在关系性数据库中,这个想法也不是什么新的东西:比如,矢量编程也被大量用于 Vectorwise 系统中。
通常有两种不同的加速查询处理的方法:矢量化查询执行和运行时代码生成。在后者中,动态地为每一类查询生成代码,消除了间接分派和动态分派。这两种方法中,并没有哪一种严格地比另一种好。运行时代码生成可以更好地将多个操作融合在一起,从而充分利用 CPU 执行单元和流水线。矢量化查询执行不是特别实用,因为它涉及必须写到缓存并读回的临时向量。如果 L2 缓存容纳不下临时数据,那么这将成为一个问题。但矢量化查询执行更容易利用 CPU 的 SIMD 功能。研究表明,将两种方法结合起来是更好的选择。ClickHouse 使用了矢量化查询执行,同时初步提供了有限的运行时动态代码生成。
StarRocks 整体上架构?较简单,有两层结构,黄?的是 FrontEnd 节点,蓝?的是 BackEnd 节点:
? FrontEnd 节点主要负责元数据的管理和客户端链接的管理,并且根据元数据信息进? 查询的规划和查询的调度。从 MySQL 客户端发起的请求通过 FrontEnd 节点转化成分 布式的 AST,也就是我们所说的执?计划树,推送给对应的 BackEnd 节点。每?个 FrontEnd 节点都存储全量的元数据,通过类 Paxos 协议进?数据同步,这种多数派的 数据同步协议也保证了我们可以线上?平阔所容 FrontEnd 节点。
? BackEnd 节点主要负责数据存储及 SQL 的计算?作。FrontEnd 节点按照?定的策略 将数据分配给对应的 BackEnd 节点。在执? SQL 计算时,?条 SQL 语句?先会按照 具体的语义规划成逻辑执?单元,然后再按照数据的分布情况拆分成具体的物理执? 单元在 BackEnd 中进?计算。BackEnd 节点是完全对等的,数据通过 Qurom 协议进 ?同步。BackEnd 节点同样也?持在线?平阔缩容。
StarRocks 是通过 MPP 多机并行机制来充分利用多机的资源,通过 Pipeline 并行机制来充分利用单机上多核的资源,通过向量化执行来充分利用单核的资源,进而达到极致的查询性能。
StarRocks 执?器的?个重?的特性就是向量化引擎。通过向量化引擎,可以极?程度的提?查询性能。
作为?个列存数据库,StarRocks 的数据在 BackEnd 存储层是以列的形式组织的。 在没有做向量化引擎之前,数据以列的形式存储,但以?的形式被加载到内存中。?如说我 们要计算 A 列与 B 列的和,会以?的维度不停的调? CPU 的加指令,循环迭代 A0 + B0, A1 + B1,A2 + B2。
有了向量化引擎之后,StarRocks 在将数据加载到内存中时,也是按照列的形式进?布局。 通过调? CPU 的 SIMD 指令集,计算 A 列与 B 列相加,减少了连续的虚函数调?,避免 CPU 流?线被打断。
通过向量化引擎的加速,过滤操作?概有 5 倍左右的性能提升,聚合操作有 15 倍的性能提升,关联操作有?概 3-4 倍的性能提升。
随着数据库执行的瓶颈逐渐从 IO 转移到 CPU,为了充分发挥 CPU 的执行性能,StarRocks 基于向量化技术重新实现了整个执行引擎,向量化执行引擎是为了充分利用单核 CPU 的能力。
向量化在实现上主要是算子和表达式的向量化,上图左边是算子向量化的示例,上图右边是表达式向量化的示例,算子和表达式向量化执行的核心是批量按列执行。相比于单行执行,批量执行可以有更少的虚函数调用,更少的分支判断;相比于按行执行,按列执行对 CPU Cache 更友好,更易于 SIMD 优化。
向量化执行不仅仅是数据库所有算子的向量化和表达式的向量化,而是一项巨大和复杂的性能优化工程,包括数据在磁盘、内存、网络中的按列组织,数据结构和算法的重新设计,内存管理的重新设计,SIMD 指令优化,CPU Cache 优化,C++ Level 优化等。经过努力,StarRocks 向量化执行引擎相比之前的按行执行,取得了整体 5 到 10 倍的性能提升。
一条SQL到执行经过了一系列的优化:
?