首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >StarRocks 物化视图2 - 查询优化

StarRocks 物化视图2 - 查询优化

原创
作者头像
jasong
发布2025-09-15 19:44:02
发布2025-09-15 19:44:02
2650
举报
文章被收录于专栏:ByConityByConityLakeHouseImpala

1 VELTA JOIN

Query Delta Join 是指查询中 Join 的表是物化视图中 Join 的表的超集的情况。例如,以下查询 Join 了表 lineorder、表 customer 和 表 part。如果物化视图 join_mv1 仅包含 lineordercustomer 的 Join,StarRocks 可以使用 join_mv1 来改写查询。

View Delta Join 指的是查询中 Join 的表是物化视图中 Join 的表的子集的情况。通常在涉及大宽表的情景中使用此功能。例如,在 Star Schema Benchmark (SSB) 的背景下,您可以通过创建物化视图,Join 所有表以提高查询性能。测试发现在通过物化视图透明改写查询后,多表 Join 的查询性能可以达到与查询相应大宽表相同的性能水平。

Code

代码语言:java
复制
    public enum MatchMode {
        // all tables and join types match
        COMPLETE,
        // all tables match but join types do not
        PARTIAL,
        // all join types match but query has more tables
        QUERY_DELTA,
        // all join types match but view has more tables
        VIEW_DELTA,
        NOT_MATCH
    }

    public OptExpression rewrite() {
        final OptExpression queryExpression = mvRewriteContext.getQueryExpression();
        final OptExpression mvExpression = materializationContext.getMvExpression();
        final List<Table> queryTables = mvRewriteContext.getQueryTables();
        final List<Table> mvTables = MvUtils.getAllTables(mvExpression);

        MatchMode matchMode = getMatchMode(queryTables, mvTables);
      
     public static MatchMode getMatchMode(List<Table> queryTables, List<Table> mvTables) {
        MatchMode matchMode = MatchMode.NOT_MATCH;
        if (queryTables.size() == mvTables.size() && Sets.newHashSet(queryTables).containsAll(mvTables)) {
            matchMode = MatchMode.COMPLETE;
        } else if (queryTables.size() > mvTables.size() && queryTables.containsAll(mvTables)) {
            matchMode = MatchMode.QUERY_DELTA;
        } else if (queryTables.size() < mvTables.size() && Sets.newHashSet(mvTables).containsAll(queryTables)) {
            matchMode = MatchMode.VIEW_DELTA;
        }
        return matchMode;
    }

代码语言:java
复制
    private boolean canMVRewriteIfMVHasExtraTables(MaterializedView mv,
                                                   Set<Table> queryTables) {

        // 1. when mv has foreign key constraints, it's ok whether query has extra tables or mv has extra tables.
        if (mv.hasForeignKeyConstraints()) {
            return true;
        }
        Set<Table> baseTables = mv.getBaseTableInfos().stream().map(x -> x.getTableChecked())
                .filter(x -> !x.isView() && !x.isMaterializedView())
                .collect(Collectors.toSet());
        Set<Table> extraTables =  baseTables.stream().filter(t -> !queryTables.contains(t)).collect(Collectors.toSet());
        if (extraTables.isEmpty()) {
            return true;
        }
        // 2. otherwise extra base tables should contain foreign constraints
        if (extraTables.stream().anyMatch(baseTable -> !(baseTable.hasForeignKeyConstraints() ||
                baseTable.hasUniqueConstraints()))) {
            Set<String> extraTableNames = extraTables.stream().map(Table::getName).collect(Collectors.toSet());
            logMVPrepare(connectContext, mv, "Exclude mv {} because it contains extra base tables: {}",
                    mv.getName(), Joiner.on(",").join(extraTableNames));
            return false;
        }
        return true;
    }

代码语言:java
复制
    private OptExpression rewriteViewDelta(List<Table> queryTables,
                                           List<Table> mvTables,
                                           PredicateSplit mvPredicateSplit,
                                           ReplaceColumnRefRewriter mvColumnRefRewriter,
                                           OptExpression queryExpression,
                                           OptExpression mvExpression) {
        // short circuit for tables without foreign-key/primary-key
        if (!optimizerContext.getSessionVariable().isEnableKeMvOp()
                && mvTables.stream().allMatch(table -> !table.hasForeignKeyConstraints())
                && !materializationContext.getMv().hasForeignKeyConstraints()) {
            logMVRewrite(mvRewriteContext, String.format("query table size:%d, mv table size:%d, " +
                    "can not try view delta rewrite because no FK constraints", queryTables.size(), mvTables.size()));
            return null;
        }

结论

1 foreign_key_constraints 需要约束事实表

2 foreign_key_constraints 需要约束物化视图

3 unique_constraints 需要约束维度表

4 unique_constraints 需要约束物化视图

5 相关key 事实表与维度表数据类型需要一直,线上是报错的

属性

描述

支持版本

foreign_key_constraints

创建 View Delta Join 查询改写的异步物化视图时的外键约束。

v2.5.4+ v3.0+

unique_constraints

创建 View Delta Join 查询改写的异步物化视图时的 Unique Key 约束。

v2.5.4+ v3.0+

mv_rewrite_staleness_second

查询改写时,物化视图数据的 Stalness 容忍度。

v3.1+

2 物化成功率

代码语言:sql
复制
-- 物化视图成功优化 StarRocks支持将物化视图刷新任务的部分中间结果落盘
ALTER MATERIALIZED VIEW mv2 SET ('session.enable_spill' = 'true');
-- 3.2 版本物化视图刷新任务的默认超时时间为5分钟,v3.2版本之后默认为1小时。
ALTER MATERIALIZED VIEW mv2 SET ( 'session.query_timeout' = '4000' );

3 分区级物化

T+1

T+1更新:当被关联基表的某个分区中的数据发生变化时,物化视图中相应的分区将被刷新,但不影响其他分区。在事实表更新后,物化视图中相应的分区将自动刷新。

Base 表增量刷新
Base 表增量刷新

主表Trigger

DIM更新:通常,维度表中的数据更新将导致所有关联结果的刷新,刷新代价较大。您可以选择忽略某些维度表中的数据更新,以避免刷新整个物化视图,或者您可以指定一个时间范围,从而只有在该时间范围内的分区才能被刷新。核心逻辑 by excluded_trigger_tables + excluded_refresh_tables

(问题) 少量dim数据与物化视图不一致

一个物化视图仅能与一个基表做分区关联

  • partition_refresh_number:每次刷新操作中要刷新的分区数。
  • partition_ttl_number:要保留的最近分区的数量。
  • excluded_trigger_tables:为避免触发自动刷新而需要忽略的表。
  • auto_refresh_partitions_limit:每次自动刷新操作中要刷新的分区数。
  • excluded_refresh_tables: 物化视图刷新时排除需要刷新的表,通常和 excluded_trigger_tables 搭配使用。

主表tiggger, dim表忽略
主表tiggger, dim表忽略

二次物化

在异步物化视图的基础上,支持创建同步物化视图,不支持创建同步物化视图

Do not support create synchronous materialized view(rollup) on MATERIALIZED_VIEW table[xxx]

直接查询异步物化视图 + mv cache

-(200)ms

在复杂查询情况下,一个查询改写过程有时候时非常复杂的

1 我们可以直接查询物化视图表

2 我们可以物化查询SQL命中的物化情况

Other

特性

描述

支持版本

排序键

支持使用 ORDER BY 指定物化视图的排序键。

v3.1+

中间结果落盘

支持通过 enable_spill 属性启用中间结果落盘,避免在物化视图构建期间出现 OOM。

v3.1+

资源组

支持通过 resource_group 属性指定物化视图构建的资源组,以实现资源隔离。

v3.1+

基于视图创建物化视图

支持基于逻辑视图创建物化视图。

v3.1+

在物化视图上创建索引

支持在物化视图上创建索引加速点查询。

v3.0.7+ v3.1.4+ v3.2+

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 VELTA JOIN
    • Code
    • 结论
  • 2 物化成功率
  • 3 分区级物化
    • T+1
    • 主表Trigger
  • 二次物化
    • 直接查询异步物化视图 + mv cache
  • Other
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档