StarRocks 技术内幕 | 多表物化视图的设计与实现
#01
物化视图的需求分析
—
1什么是物化视图要了解物化视图可以先了解视图的概念。视图是一个虚拟表(也可以认为是一条语句),基于它创建时指定的查询语句返回的结果集。而物化视图则是将这个虚拟表进行实体化,其本身可以理解为是一个特殊的表。
2物化视图的应用场景
物化视图最常见的场景是,由基础的 Base 表通过创建物化视图的 SQL 生成物化视图,当用户查询相似的 SQL 时,查询优化器可以自动 QueryRewrite 复用物化视图,从而达到查询加速的效果。在 2.4 之前,我们仅支持的是单表同步的物化视图,但它缺乏一些复杂场景的支持,例如只能支持一些简单的 SQL。对于一个实时的场景,比如用户有两张实时表进行 Join 操作,由于单表同步物化视图不支持多表 Join 操作,这种场景就无法支持了。对于离线多表加速建模的场景,通常需要事实表和维度表的 Join 的操作。这里面有两方面的需求,一方面是加速的需求,希望我们在查这些 Base 表时通过 QueryRewrite 加速查询;另一方面是建模的需求,希望物化视图能够屏蔽后面的事实表和维度表,也就是说希望物化视图可以直接进行查询。还有一类场景,这类场景虽然也可以支持,但是支持得不是很好,就是当物化视图的计算结果比较少的时候,希望分区分桶比较少,这样查询性能才会比较好。之前同步的模型,物化视图与 Base 表是一对一的关系,可能就会出现创建物化视图虽然结果很少,但是分区分桶很多,反而出现查询性能下降的现象。根据这些场景和问题,接下来我们看看可以怎么去解决这些问题。
#02
物化视图的设计
—
我们观察到 SQL 复杂度越低,数据的同步性越好做,当 SQL 复杂度越高,数据的同步性越来越难做。之前的同步物化视图,其实是选择了同步性最佳的点,但它的弊端就是 SQL 很复杂的时候很难做。但是用户的大部分场景 SQL 可能是很复杂的,并且可以接受一定的异步延迟,所以可以牺牲一定的同步性,满足复杂 SQL 加速的场景。于是就有了异步刷新的解决方案。
2异步刷新的解决方案首先我们看看怎么解决之前的实时场景的问题。在我们使用新版创建物化视图时,可以通过 PARTITION BY 关键字来指定物化视图跟某一个 Base 表的一个分区进行绑定,当前的版本分桶是必填的,但是分桶是可以灵活变化的,然后还可以指定刷新的起始时间点和间隔。
我们创建物化视图语句里面的 Query 语句本身是基本没有任何限制的,可以写得很复杂,只要是可以查询的基本都可行。对于实时的场景,它其实是只刷新某一个分区的小部分数据量。对于实时表,导入非常频繁的,用户可以接受分钟级刷新的场景下,用户可以使用周期性刷新,例如每 1 分钟刷新一次,这样可以避免刷新频率过高导致物化视图刷新触发过于频繁。
然后我们再看看离线的场景,离线场景 Base 表,通常事时表基本上只有每天才会去刷新某一个分区,维表会全量刷新一个分区。这里我们在创建物化视图时,可以指定 REFRESH ASYNC,当每个 Base 表有数据变化的时候,它会自动去判定哪些分区需要刷新并进行智能刷新,对于不需要刷新的分区就不刷新。离线场景也可以支持以天为周期进行调度。离线的场景下由于数据量比较大,有可能查询需要调整一些特殊的 Session Variable 参数才能够刷新成功,这些特殊的参数可以通过 Query 里面的 SELECT hint 来传入。但是物化视图其是一个需要长期打磨的功能。周期性刷新和触发式刷新覆盖不了所有的场景,有可能用户在不需要刷新的时候,还花费了很多刷新的成本。所以我们提供了一个手动刷新的功能,让用户能灵活地控制刷新的时机,也就是通过指定 REFRESH MANUAL。等到物化视图在后面的版本越来越完善的时候,使用手动刷新的情况会渐渐较少。
另外之前还提到了分区分桶浪费的问题,关于解决这个问题的方法,可以通过指定PARTITION BY DATE_TRUNC("month", dt),这样我们就可以把 dt 这一列本来按天的 Base 表上卷到按月分区的表,从而来减少分区浪费的问题。同时我们也可以指定 Bucket 的数量,而不是跟 Base 表保持一致。这样在物化视图的结果很少的情况下,我们可以灵活减少分区和分桶,从而提高查询性能,避免分区分桶的浪费。
以上讲的这些都是 StarRocks 2.4 已经实现的功能,这些功能是 StarRocks 和社区共同讨论并实现的。在这里要感谢社区的小伙伴们。
#03
物化视图的实现原理
—
先来了解一下多表物化视图的框架,即数据模型。在早期的版本中,我们实际上支持的是单表同步物化视图,也就是我们基于一个原始表去创建物化视图,实际上物化视图是以索引的形式去存在的。
在左图中可以看到表的基础索引中的 Tablet 和物化视图索引的 Tablet 是一一对应,但是在多表异步的物化视图的框架中,Tablet 不是一一的对应关系,物化视图实际上是以表的模型去做实现的。以右图为例,假设 Base 表有两个 Partition A 和 B,假设物化视图有 Partition C,那么 Partition A、Partition B 的 Tablet 和物化视图的 Partition C 中的 Tablet 是映射关系,这种关系不是一一对应的关系。
那么以上是多表异步物化设图的三种核心技术的实现原理。除此我们还需要考虑物化视图失效的问题。
上述这些都是 2.4 版本已经实现的功能。StarRocks 2.4 版本是一个预览版本,需要通过设置 FE 参数 enable_experimental_mv 开启使用。
#04
StarRocks 2.5 版本展望
—
2.4 版本还有三个比较重要的功能没有实现。一是不支持从外表去创建物化视图,2.4 的版本只支持在一个数据 DB 上去创建物化视图,并不支持跨 DB 创建物化视图;二是不支持创建基于物化视图的物化视图;三是还不支持最重要的 QueryRewrite 功能。
回看 StarRocks Summit Asia 2022
关于 StarRocks
面世两年多来,StarRocks 一直专注打造世界顶级的新一代极速全场景 MPP 数据库,帮助企业建立“极速统一”的数据分析新范式,助力企业全面数字化经营。
2021 年 9 月,StarRocks 源代码开放,在 GitHub 上的星数已超过 3500 个。StarRocks 的全球社区飞速成长,至今已有超百位贡献者,社群用户突破 7000 人,吸引几十家国内外行业头部企业参与共建。
StarRocks 技术内幕:
👇 阅读原文回看 StarRocks Summit Asia 2022