• 卢经理 151 5399 4549
    扫一扫,加我咨询
扫码关注我们
StarRocks 如何借助物化视图加速数据分析
发布时间:2023-09-18

一、StarRocks数据湖分析

1、StarRocks 3.0 Overview

图片

StarRock3.0之前定位于实时数仓,主要有以下几方面的能力:

  • 实时写入:从Kafka、Flink等系统实时插入、更新、删除数据的能力。
  • 批量导入:从 S3、Hadoop、Spark 等各种系统批量导入数据的能力。
  • 实时引擎:具备实时存储引擎和实时查询引擎,在dashboard、BI、Ad-hoc query等各种场景中,都有比较好的性能和统一性。

StarRocks3.0推出了新的数据湖分析功能,支持Hive、Iceberg、Hudi,和MySQL等传统DB外表,加上StarRocks本身的外表,使得StarRocks 能够作为一个统一的查询引擎,去查询各种数据源。基于这些能力,我们希望把 StarRocks 打造成一个实时的Lakehouse产品,更好地整合数据湖和数据仓库这两种产品概念。

2、StarRocks LakeHouse

图片

LakeHouse可以分为传统数仓和数据湖两大块:

  • 传统数仓:用户一般会进行数据清洗、宽表加工以及聚合,它的数据质量通常比较好,不用太担心数据格式问题,因此查询性能比较好。StarRocks对执行引擎、数据存储格式、自带的向量化引擎、实时更新引擎、存储引擎以及各种执行算子等做了很多优化,实时更新的性能通常可以达到秒级。
  • 数据湖:它的优势是Table format、File format和生态等方面比较open,能够很容易地接入各种查询引擎、存储引擎,所以它能够成为很多企业的统一存储;另外它比较适合于作为source of truth的存储,比如整个企业里的数据统一放在数据湖里面,然后在上层基于这个数据底座去做更多的数据加工跟处理。数据湖的扩展性较好、性价比比较高,它可以是基于S3等大数据生态技术演进过来的,可以基于HDFS、S3等存储介质。

湖仓目前看来还是有较大gap的、割裂的两个场景,StarRocks做了很多技术和Feature,去整合这两种场景,从早期的Warehouse,到3.0做了较大的架构升级,具备了很好的弹性能力。支持存算分离,可以由原生存储变成S3。支持多种部署方式,可以选择线下部署,也可以选择K8s等部署方式。支持数据库查询能力,可以作为一个查询引擎去查询数据湖。最终希望打造云原生弹性扩展能力,更好地整合成LakeHouse的产品形态。

3、StarRocks LakeHouse - Catalog

图片

StarRocks3.0之前需要手动创建外表DDR来查询外部数据源,在表很多的时候操作非常繁琐。3.0的Catalog功能可以直接查询Hive、Iceberg、Hudi、Deltalake、ES、Mysql、Oracle、Postgres和文件等各种数据源,覆盖了大部分的数据使用场景。

只需要执行create external Catalog命令,就可以连到Hive Metastore自动获取元数据,然后就可以直接查询其中的数据。除此之外另一种场景是在S3上放了一堆文件,但没有将其组织成Iceberg的format,也可以创建Catalog直接去查询。

在 External Catalog 的基础上,结合 StarRocks 的内表存储,两种数据源可以 Join 起来同时查询。由于内表有自己的存储引擎,具有较好的实时性,可以服务实时workload;同时External Table可以用于存储历史数据,这样就可以联合使用多种不同的存储引擎,来覆盖更多的使用场景。

4、StarRocks LakeHouse - Trino 兼容

图片

Trino、Presto有自己的SQL方言和许多自定义函数,而StarRocks目前主要兼容的是MySQL语法和协议。如果用户已经过了POC阶段,正在生产系统使用Trino、Presto等查询引擎,想要迁移到StarRocks就会有很多的工作,虽然不用迁移数据,但是需要改造很多业务SQL。

为此StarRocks做了兼容Trino的feature,在SQL parser中支持MySQL和Trino 两种方言,使用统一的执行计划,目前已经覆盖了99%的语法。用户只需要将方言切换为StarRocks,就可以实现无缝迁移,获得数倍的性能提升。

5、StarRocks LakeHouse - 极速查询性能

图片

数据湖由File format和Table format两部分组成,File format通常会用比较高效的ORC、parquet,Table format通常会用Iceberg、Hudi。

数据湖跟内表存储引擎理念比较接近,没有太多本质差别,但是在具体的细节上还是有些差别的,比如说文件格式、文件压缩效果、IO效果以及整体性能等。HDFS和S3等不同的存储系统虽然可以提供统一的接口,但它们是有性能差异的,HDFS通常在Latency上会比S3的性能稍微好一些,有些场景下S3会有更好一些。ORC的IO counter可能比parquet要多非常多,也就是parquet可以IO size更大一些。

考虑到这些情况,StarRocks内部做了非常多的IO优化,去克服不同系统之间的性能差异。

图片

上图是用eBPF之类的工具观察到的结果,可以看出在数据湖场景下更加IO密集,传统数仓场景下往往是计算密集。有些用户的写数系统比较复杂多样,数据格式质量不那么好,产生了很多parquet小文件。有些用户ORC的stripe size设置得非常小,如果按传统策略每个row group里面读每个column,它的IO会非常小可能就几KB,效率非常低,我们也不能把IO粒度扩大到文件级别,因为可能某一个文件非常大。

StarRocks针对不同IO密集场景做了优化。

如果column size非常小就合并IO,一次读取多个column。

如果文件非常小,就一次读取整个文件,即便文件中有一些数据可能并不需要,但在做了这样一个合并之后,总IO次数会少非常多。

如果使用了S3存储,不管你怎么优化,当访问它的冷数据的时候,它的IO消耗一定会非常高,最好的优化方式是把数据cache在本地。相较于Presto、Trino会用一些三方组件去做数据cache, StarRocks 希望把系统架构做得更简单一些,所以自己实现了一套协同memory和disk的cache系统,数据会先cache在memory中,当memory 不够时数据会溢出到disk上。通常来说大部分workload都会有一个相对比较小的working set,比如有几百GB的数据要分析,当多次查询后,大部分数据都能够命中cache,从而得到比较好的查询性能。

除此之外 StarRocks 也做过一些算法层面的IO优化,比如延迟物化技术,会根据查询条件中的where条件先把某一列查出来,再造一个过滤去读其它列。还有Top N算子,也可以做延迟物化,后面我们可能也会在join也支持延迟物化技术。

综合使用各种IO优化技术,可以很大程度上减少文件IO。在同样的数据集、同样的资源规模下,StarRocks查询Iceberg比Trino快3-5倍。在大部分用户案例中,从Trino切换到StarRocks都会有一个非常明显的性能提升,像TPC-H其实是一个相对没有那么复杂的数据集,如果用户的实际业务中有一些特别复杂的SQL,它会有更加明显的性能提升。

6、StarRocks LakeHouse - 统一开放

图片

StarRocks在架构层面和功能技术层面做了很多整合,比如物化视图、Catalog、IO优化以及Trino兼容等,希望这些技术能够整合起来,打造成统一开放的Lakehouse架构。

StarRocks可以作为查询引擎去查询数据湖中的数据,替换Spark、Flink等相对比较老的组件。StarRocks 也有自己的存储引擎,它可以提供 Colocate能力,以及用户指定的分区、排序、分桶能力,和实时场景下需要的实时更新以及索引的能力。

综合使用这些技术,使得用户可以让一部分workload放在数据湖里,继续使用Spark、Flink做加工处理,另一部分更偏实时的workload放在内表里,然后用 StarRocks 作为统一的查询入口,也可以让实时workload通过StarRocks写入。结合起来,比较好地实现了实时 LakeHouse这样的架构。

二、StarRocks 物化视图

1、StarRocks Materialized View

图片

物化视图的语法有几个部分:

partition by:对物化视图分区,和StarRocks内表一样,可以按照时间等维度进行分区。分区后可以对查询裁剪,避免访问不需要的数据,比如按天分区后就只需要刷当天的数据,历史数据不需要去touch。还可以进行分区级的数据自动刷新、数据变更的自动订阅,实现比较好实时性。

Refresh:支持全量刷新、增量刷新、定时刷新、手动刷新等多种方式。满足不同业务场景的需求。

resource group:把物化视图跟其它workload更好地整合在同一个系统、同一个集群里。因为用户的查询是一种偏前端的workload,而物化视图的维护是偏后端、资源非常密集的workload,所以如何把这两种整合到一起,稳定地跑到同一个集群里面,是一个很大的技术难点。所以我们这里选择用 resource group 技术来实现资源隔离。

查询语句:支持aggregation、join等查询语句。

对不同的查询语句类型可以使用不同的刷新方式,如果是简单的聚合查询可以增量刷新,如果有join或者更复杂的语句就要全量刷新。未来StarRocks会逐步扩展物化视图的增量刷新能力,支持更多的复杂使用场景,比如增量的 join 窗口,类似Flink 的增量计算等等。

生产环境中有很多适合用物化视图的场景,例如:

增量聚合:很多业务报表会对immutable的event、log数据做sum、distinct、bitmap、Hyperlog等聚合,这类数据一般数据量非常大、写入TPS高,所以不适合全量刷新。之前常用Flink来做增量计算,像sum、bitmap去重以及Hyperlog等,现在也可以用StarRocks的增量物化视图来支持。

数仓建模:物化视图的语法非常适合替代传统ETL用来建模。业务有时可能不太关心增量刷新还是全量刷新,也不太关心数据之间的依赖关系如何表达、如何调度,就可以使用DBT这种工具直接用物化视图去建模,它还可以屏蔽底层的刷新方式。

透明加速:用户可以透明地创建出一个物化视图,然后利用优化器的查询改写能力,改为查询物化视图来实现很好的加速效果。

数据湖加速:数据湖查询往往是IO密集型的,一般可以使用cache来优化,但如果数据量非常大就无法cache在本地。这时可以借助物化视图来预计算,计算结果的数据量通常会小几个数量级,再把计算结果cache到本地,就可以很好地加速数据湖的查询。

2、MV - 数仓建模

图片

传统数仓建模可以分ODS、DWD、DWS、ADS几层,每层可能都会用到Hive、Sqoop以及Flink等ETL工具,现在也可以用StarRocks物化视图技术来构建。从ODS到DWD往往是聚合和清洗,这一层可以用物化视图的SQL谓词和增量聚合技术来构建。再往上可能会做宽表join以及面向具体业务的报表,往往需要比较复杂的join,或者窗口函数的计算,也可以用物化视图来表达。

它带来价值是能够简化架构的复杂度,不需要在外部维护很多的数据组件去做加工,如果维护了这些数据组件,不仅要使用物理资源去部署运行,还需要部署一些调度、监控的组件去支持,这样的架构是比较复杂的。如果迁移到物化视图上面来,就只需执行几条SQL,不需要额外维护组件,物化视图还维护了调度关系。

另外还能充分利用StarRocks执行引擎的性能优势,如果使用Hive等外部系统,数据可能先要过一遍Hive,中间的计算开销以及IO开销就会非常的消耗资源,然后再往下游系统写数据,它的IO又会多了几倍,一旦有很多的IO开销以及组件,整体性能就很难优化,非常消耗资源,ETL任务的实时性也很难保障。

迁移到StarRocks就可以很好地解决这些问题,主要用到下面几个关键技术:

  • 支持多数据源:可以基于内表、数据湖外表和JDBC外表等创建物化视图,比如可以对MySQL、Postgres创建物化视图,把数据同步到内部来,这样就可以不用直接查外部数据了。
  • 维护分区关系:对内表和外表的分区关系进行维护,使得全量刷新可以依靠分区去做更细粒度的数据刷新和物化视图维护。
  • 任务调度:物化视图join表的时候可以显示声明依赖关系,被join的表更新完成后才刷新视图。如果有多张表作为事实表,还可以使用接口手动控制调度、定制业务集。
  • 资源隔离:在使用物化视图替代传统数仓建模的时候,只需要添加一个新的resource-group,不需要部署新的集群,让多个workload跑在同一个系统集群中。

图片

上图中T1是事实表,T2是维度表,列举了一些分区刷新的经典场景:

事实表细粒度刷新:维度表的变化频率是相对比较低的,如果事实表做了比较细粒度的分区,比如天级、小时级或分钟级的分区,在事实表刷新之后,基于分区就可以发现物化视图对应的某一个分区也需要更新,那就只需要刷新一个分区,代价是相对比较低的。

维度表精准刷新:最经典的场景是刷新整个物化视图,代价相对较大。有些业务像酒店餐饮是可以不回刷数据的,那么可以精细化的排除某些维度,不触发回刷。也有一些业务,希望回刷比如一个月的数据,那么可以精准的控制回刷几个分区。

自动刷新:StarRocks支持订阅外表分区的数据变更,当发现Hive等外表分区变更后,可以自动刷新物化视图对应的分区。

3、MV - 弹性资源隔离

图片

StarRocks实现了统一的架构,能够同时运行Ad-hoc query、Dashboard、Realtime、Batch等多个workload。Realtime物化视图时效性要求通常比较高,比如实时看板一般是分钟级,所以资源消耗比较大。Batch物化视图允许慢一点一般是天级,通常是在半夜定时去跑,所以不需要占用非常多的资源。那么如何资源隔离,使不同的workload不会互相影响,就成为了一个难题。目前StarRocks用了资源组软性隔离和Warehouse硬性隔离两个技术来实现资源隔离。

资源组软性隔离:用户可以使用默认资源组,或者根据业务需要创建资源组,非常细腻的控制每个视图的CPU、Memory、Disk等资源的最大配额占比。当只有1个workload 时允许跑到100%,当有多个workload时,就根据配额的比例分配资源,因为是软性,所以加起来可以超过100%。

Warehouse硬性隔离:在云原生架构实现了无状态计算节点的架构。物化视图可以放在独立的节点运行,将资源彻底隔离开来。Warehouse 本身是弹性的,可以随时创建、释放。

4、MV - 透明查询加速

图片

在BI 报表场景的SQL很多是系统自动生成的,而且通常很复杂,用户很难通过修改SQL的方式来进行调优,所以需要一种类似于传统数据库索引的透明加速能力。

物化视图针对SPJG(select、project、join、group by)场景,支持查询改写加速。比如有两表的join再聚合的query,我们可以创建一个逻辑一样的物化视图,在query时直接scan这个物化视图,这是exactly match的。如果还有聚合计算,或者聚合key、表达式有区别,那么可以在这个物化视图的基础上做二次的聚合、join计算。

案例1:聚合上卷改写

图片

上图右边是物化视图,有时间和city两个维度。可以采用类似某些系统的Cube来加速查询,在创建Cube的时候就把所有维度都预计算出来,后面的查询几乎不需要做任何计算。但是如果维度很多,会导致维度组合数量爆炸。物化视图可以把常见的维度预聚合,比如把时间和城市预聚合,比如一天有几亿数据,按天聚合后数据量会少几个量级,带来的效果非常显著。

上图左边是三个实际的查询,查询语句不需要跟物化视图一样,否则就比较鸡肋了。大部分查询的维度组合是比较灵活的,维度也不一定和物化视图一致,所以需要上卷以及更多的探索。示例1的查询按照时间维度聚合count,count是可以上卷的,只需要把物化视图按照city聚合count一次,所以优化器会自动改写为基于物化视图的上卷。示例2按照city聚合也是一样可以上卷。上卷之后可以获得更多的维度组合,有比较好查询加速效果,同时也会兼顾灵活性,还有一些特殊的case是做count distinct,需要结合Bitmap技术,在底层创建物化视图的时候同时创建bitmap,然后在上面就可以做更多的维度的组合了。

案例2:宽表join改写

图片

join是非常常见的数据加工方式,宽表join的物化视图可能把事实表和多个维度表join起来。查询的时候比较灵活,可能join结果并不需要所有维度,只需要join其中一部分。因为join类型有很多,inner join跟outer join不一样,一对一join跟一对n join也不一样,会有一些参数和其他的语法去适配不同的场景,可能把inner join改成其他join方式,也可能完全改写到物化视图上去,剔除掉其中不需要访问的那些数据。

5、MV案例 - 实时精准去重

图片

国内某共享出行公司有几十个实时看板,需要做精确的count distinct,运营人员要求数据新鲜度达到分钟级、并发达到100。之前维护了很多Flink job做增量计算,结果发现直接去现算几乎是不可能的,每次计算可能需要几秒钟,因为它的distinct有千万级。之前的系统使用了HypoLogLog技术模糊去重后再count distinct,数据新鲜度比较好,但结果是不精确的。

使用StarRocks替换Flink系统后,资源成本和维护成本都减少了很多。优化方案是使用StarRocks做两层物化视图:

第一层在明细数据上按照城市、时间做增量聚合,可以用bitmap技术和物化视图增量更新技术,先聚合成城市粒度、分钟级的数据。

第二层用物化视图做面向ODS的分钟级刷新视图,因为有几十个看板,所以视图非常多,分钟级刷新是能够比较好地权衡数据新鲜度和资源使用。

这些看板的SQL不方便修改,所以还用了物化视图的透明加速能力,自动改写替换掉它这个报表中的一些SQL。因为第一层已经做了增量聚合,所以第二层计算量比较小,不需要做非常重的聚合计算,只需要把物化视图的结果做一些简单的过滤就可以返回了。

StarRocks权衡了数据新鲜度和性能,现在100并发时latency 大概由3秒缩减到了30毫秒,并且实现了精确的1分钟新鲜度的count distinct。

三、MV for LakeHouse

图片

物化视图相关的技术,包括构建外表物化视图、分区关系维护、自动刷新、改写SQL等等,都可以和数据湖整合起来,使得在外表的场景能够用物化视图加速。其中外表的查询改写和内表还是有一些差异的,比如Hive可能声明一些外键约束、唯一键约束,在查询改写过程中是需要这些信息的,我们可以用其它一些方式把这些信息透传过来,然后就能在优化期器中用于查询改写。这几个技术结合起来实现了比较好的查询加速效果。

数据湖的架构往往是比较复杂的,接下来看几个案例。

案例1: 分层建模

图片

分层建模分为以下四层:

ODS层可以是数据湖外表,存储历史数据。

DWD层使用外表物化视图把数据清洗后放到StarRocks内部存储,以及用PK表可以实时地把TP等数据同步进来,可以用来存储实时数据。

DWS层用了物化视图和逻辑视图两种技术,物化视图把结果给物化下来用于加速查询,逻辑视图仍然可以访问实时数据用于简化业务逻辑,把这两种技术结合起来就可以面向不同的业务场景、实现不同的效果。

ADS层用逻辑视图把很多的业务数据给union起来,以及做一些更面向业务的表达。

这样分层后相对更加灵活,实现了近实时的实时性。存储也比较开放,历史数据仍然可以存在数据湖中。中间的数据刷新部分也不用维护,而且仍然可以用其他的查询引擎。

案例2:实时数据湖

图片

严格来说,实时数据湖并不是一个产品或者一个Feature,而是一种解决方案。目前 StarRocks 会结合 Iceberg 以及一些其他Feature,去实现LakeHouse 场景的实时聚合、实时更新,实现整体的解决方案。

实时聚合:主要面向immutable的数据,这类数据可以直接去写Lake,使用Iceberg这种数据湖的写入吞吐量会比较高。

实时更新:主要面向mutable的数据,数据湖目前还没有较好的实时更新能力,StarRocks primary key则可以很好的支持,所以首先会把数据写到pk表,定时下沉到Lake中,同时在此之上,可以用物化视图做实时的增量聚合。

结合实时聚合和实时更新两种场景,把全量数据存在Iceberg中,把聚合、更新数据放在StarRocks中,然后在上层构建物化视图去做面向业务的加工宽表、聚合结果,可以带来以下几方面的业务价值:

  • 一是SSOT,不管是面向归档,还是面向其它查询引擎,都能直接查询数据湖,不会被封闭在一个系统里。
  • 二是变成实时后,可以分摊资源,不会在凌晨出现一个业务高峰,而白天又很空闲,导致资源浪费。
  • 三是可以发挥不同存储引擎的优势,StarRocks支持实时聚合、实时更新,数据湖可以存储历史数据,具有超高的写入吞吐量的优势。

四、总结展望

图片

StarRocks 后续有几个发展方向:

第一个是利用云原生架构更好地管理资源,在接入数据湖并构建很多ETL workload之后,如何把各种资源统一管控起来,将会是一个很大的挑战。

第二个是支持更多的ETL的场景,物化视图目前还不能解决全部ETL场景,无法彻底替换Flink,所以未来会开发更多的ETL的feature,更好地把ETL场景统一起来。

第三个是进一步加强实时链路,会针对数据摄取和数据实时计算等场景开发更多的feature,让导入各种实时系统的数据变得更加容易,会支持更多的增量计算场景,而不仅仅是实时聚合。

五、问答

问:物化视图底层存储也是用三副本吗?

答:对。物化视图也是按照表来存储的,不同于普通表的是会自动维护。Base表跟物化视图表的存储都取决存储引擎,可以设置3副本,可以设置2副本,也可设置1副本,也可以用云原生架构做存算分离,是非常灵活的,关键在于如何维护这个base表跟计算结果的映射关系。