
Query Delta Join 是指查询中 Join 的表是物化视图中 Join 的表的超集的情况。例如,以下查询 Join 了表 lineorder、表 customer 和 表 part。如果物化视图 join_mv1 仅包含 lineorder 和 customer 的 Join,StarRocks 可以使用 join_mv1 来改写查询。
View Delta Join 指的是查询中 Join 的表是物化视图中 Join 的表的子集的情况。通常在涉及大宽表的情景中使用此功能。例如,在 Star Schema Benchmark (SSB) 的背景下,您可以通过创建物化视图,Join 所有表以提高查询性能。测试发现在通过物化视图透明改写查询后,多表 Join 的查询性能可以达到与查询相应大宽表相同的性能水平。
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;
} 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;
} 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+ |
-- 物化视图成功优化 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' );T+1更新:当被关联基表的某个分区中的数据发生变化时,物化视图中相应的分区将被刷新,但不影响其他分区。在事实表更新后,物化视图中相应的分区将自动刷新。

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 搭配使用。
在异步物化视图的基础上,支持创建同步物化视图,不支持创建同步物化视图
Do not support create synchronous materialized view(rollup) on MATERIALIZED_VIEW table[xxx]
-(200)ms
在复杂查询情况下,一个查询改写过程有时候时非常复杂的
1 我们可以直接查询物化视图表
2 我们可以物化查询SQL命中的物化情况
特性 | 描述 | 支持版本 |
|---|---|---|
排序键 | 支持使用 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 删除。