6.1.3.3 使用与实践¶
1 异步物化视图使用原则¶
-
时效性考虑:异步物化视图通常用于对数据时效性要求不高的场景,一般是
T+1
的数据。如果时效性要求高,应考虑使用同步物化视图。 -
加速效果与一致性考虑:在查询加速场景,创建物化视图时,
DBA
应将常见查询SQL
模式分组,尽量使组之间无重合。SQL
模式组划分越清晰,物化视图构建的质量越高。一个查询可能使用多个物化视图,同时一个物化视图也可能被多个查询使用。构建物化视图需要综合考虑命中物化视图的响应时间(加速效果)、构建成本、数据一致性要求等。 -
物化视图定义与构建成本考虑:
-
物化视图定义和原查询越接近,查询加速效果越好,但物化的通用性和复用性越差,意味着构建成本越高。
-
物化视图定义越通用(例如没有
WHERE
条件和更多聚合维度),查询加速效果较低,但物化的通用性和复用性越好,意味着构建成本越低。
-
需要注意:
-
物化视图数量控制:物化视图并非越多越好。物化视图参与透明改写,且
CBO
代价模型选择需要时间。理论上,物化视图越多,透明改写的时间越长,且物化视图构建和刷新占用的资源越大。 -
定期检查物化视图使用状态:如果未使用,应及时删除。
-
基表数据更新频率:如果物化视图的基表数据频繁更新,可能不太适合使用物化视图,因为这会导致物化视图频繁失效,不能用于透明改写(可直查)。如果需要使用此类物化视图进行透明改写,需要允许查询的数据有一定的时效延迟,并可以设定
grace_period
。具体见grace_period
的适用介绍。
2 物化视图刷新方式选择原则¶
当满足以下条件时,建议创建分区物化视图:
-
物化视图的基表数据量很大,并且基表是分区表。
-
物化视图使用的表除了分区表外,其他表不经常变化。
-
物化视图的定义
SQL
和分区字段满足分区推导的要求,即符合分区增量更新的要求。详细要求可参考:CREATE-ASYNC-MATERIALIZED-VIEW
-
物化视图分区数不多。
当物化视图的部分分区失效时,透明改写可以使用物化视图的有效分区 UNION ALL
基表返回数据。如果不能构建分区物化视图,可以考虑选择全量刷新的物化视图。
3 分区物化视图常见使用方式¶
当物化视图的基表数据量很大,且基表是分区表时,如果物化视图的定义 SQL
和分区字段满足分区推导的要求,此种场景比较适合构建分区物化视图。分区推导的详细要求可参考 CREATE-ASYNC-MATERIALIZED-VIEW
和异步物化视图 FAQ
构建问题 12
。
物化视图的分区是跟随基表的分区映射创建的,一般和基表的分区是 1:1
或者 1:n
的关系。
-
如果基表的分区发生数据变更,如新增分区、删除分区等情况,物化视图对应的分区也会失效。失效的分区不能用于透明改写,但可以直查。透明改写时发现物化视图的分区数据失效,失效的分区会通过联合基表来响应查询。
确认物化视图分区状态的命令详见查看物化视图状态,主要是
show partitions from mv_name
命令。 -
如果物化视图引用的非分区表发生数据变更,会触发物化视图所有分区失效,导致此物化视图不能用于透明改写。需要刷新物化视图所有分区的数据,命令为
REFRESH MATERIALIZED VIEW mv1 AUTO;
。此命令会尝试刷新物化视图,如果满足分区增量构建的条件则进行分区增量构建,否则退化为全量构建。因此,一般将数据频繁变化的表放在分区物化视图引用的分区表,将不经常变化的维表放在非引用分区表的位置。
分区物化视图的透明改写是分区粒度的,即使物化视图的部分分区失效,此物化视图仍然可用于透明改写。但如果只查询了一个分区,并且物化视图这个分区数据失效了,那么此物化视图不能用于透明改写。
举例 1
:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
在这个例子中, orders
表的 o_ordertime
字段是分区字段,类型是 DATETIME
,按照天分区。
查询主要是按照“天”的粒度,查询粒度比较粗:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
为了不让物化视图每次刷新的分区数量过多,物化视图的分区粒度可以和基表 orders
一致,按“天”分区。
物化视图的定义 SQL
的粒度可以按照“天”,并且按照“天”来聚合数据,
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
4 查看物化视图状态¶
通常物化视图会出现两种状态:
-
状态正常:指的是当前物化视图是否可用于透明改写。
-
不可用、状态不正常:指的是物化视图不能用于透明改写的简称。尽管如此,该物化视图还是可以直查的。
4.1 查看物化视图元数据¶
SQL | |
---|---|
1 2 |
|
返回结果如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
-
SyncWithBaseTables
:表示物化视图和基表的数据是否一致。-
对于全量构建的物化视图,此字段为
1
,表明此物化视图可用于透明改写。 -
对于分区增量的物化视图,分区物化视图是否可用,是以分区粒度去看的。也就是说,即使物化视图的部分分区不可用,但只要查询的是有效分区,那么此物化视图依旧可用于透明改写。是否能透明改写,主要看查询所用分区的
SyncWithBaseTables
字段是否一致。如果SyncWithBaseTables
是1
,此分区可用于透明改写;如果是0
,则不能用于透明改写。
-
-
JobName
:物化视图构建Job
的名称,每个物化视图有一个Job
,每次刷新会有一个新的Task
,Job
和Task
是1:n
的关系 -
State
:如果变为SCHEMA_CHANGE
,代表基表的Schema
发生了变化,此时物化视图将不能用来透明改写(但是不影响直接查询物化视图),下次刷新任务如果执行成功,将恢复为NORMAL
。 -
SchemaChangeDetail
:表示SCHEMA_CHANGE
发生的原因。 -
RefreshState
:物化视图最后一次任务刷新的状态。如果为FAIL
,代表执行失败,可以通过tasks()
命令进一步定位失败原因。Task
命令见本文查看物化视图Task
状态。 -
SyncWithBaseTables
:是否和基表数据同步。1
为同步,0
为不同步。如果不同步,可通过show partitions
进一步判断哪个分区不同步。show partitions
见下文分区物化视图查看SyncWithBaseTables
状态方法。
分区物化视图查看 SyncWithBaseTables
状态方法
运行 show partitions from mv_name
查看查询使用的分区是否有效,返回结果如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 |
|
主要查看 SyncWithBaseTables
字段是否为 true
。 false
表示此分区不可用于透明改写。
4.2 查看物化视图 Task 状态¶
每个物化视图有一个 Job
,每次刷新会有一个新的 Task
, Job
和 Task
是 1:n
的关系。
根据 JobName
查看物化视图的 Task
状态,运行如下语句,可以查看刷新任务的状态和进度:
SQL | |
---|---|
1 2 3 |
|
返回结果如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
-
NeedRefreshPartitions
,CompletedPartitions
记录的是此次Task
刷新的分区。 -
Status
:如果为FAILED
,代表运行失败,可通过ErrorMsg
查看失败原因,也可通过LastQueryId
来搜索Doris
的日志,获取更详细的错误信息。目前任务失败会导致已有物化视图不可用,后面会改成尽管任务失败,但是已存在的物化视图可用于透明改写。 -
ErrorMsg
:失败原因。 -
RefreshMode
:complete
代表刷新了全部分区,PARTIAL
代表刷新了部分分区,NOT_REFRESH
代表不需要刷新任何分区。
Tip
-
如果物化视图创建的时候设置了
grace_period
属性,那么即使SyncWithBaseTables
是false
或者0
,有些情况下它依然可用于透明改写。 -
grace_period
的单位是秒,指的是容许物化视图和所用基表数据不一致的时间。-
如果设置成
0
,意味着要求物化视图和基表数据保持一致,此物化视图才可用于透明改写。 -
如果设置成
10
,意味着物化视图和基表数据允许10
秒的延迟,如果物化视图的数据和基表的数据有延迟,在10
秒内,此物化视图都可以用于透明改写。
-
5 如何使用物化视图加速查询¶
使用物化视图查询加速,首先需要查看 profile
文件,找到一个查询消耗时间最多的操作,一般出现在连接( Join
)、聚合( Aggregate
)、过滤( Filter
)或者表达式计算( Calculated Expressions
)。
对于 Join
、 Aggregate
、 Filters
、 Calculated Expressions
,构建物化视图都能起到加速查询的作用。如果一个查询中 Join
占用了大量的计算资源,而 Aggregate
相对而言占用较小的资源,则可以针对 Join
构建物化视图。
接下来,将详细说明如何针对上述四种操作构建物化视图:
-
对于
Join
可以提取查询中使用的公共的表连接模式来构建物化视图。透明改写如果使用了此物化视图,可以节省
Join
连接的计算。将查询中的Filters
去除,这样就是一个比较通用的Join
物化视图。 -
对于
Aggregate
建议尽量使用低基数的字段作为维度来构建物化视图。如果维度相关,那么聚合后的数量可以尽量减少。
比如表
t1
,原表的数据量是1000000
,查询语句SQL
中有group by a, b, c
。如果a
,b
,c
的基数分别是100
,50
,15
,那么聚合后的数据大概在75000
左右,说明此物化视图是有效的。如果a
,b
,c
具有相关性,那么聚合后的数据量会进一步减少。如果
a
,b
,c
的基数很高,会导致聚合后的数据急速膨胀。如果聚合后的数据比原表的数据还多,可能这样的场景不太适合构建物化视图。比如c
的基数是3500
,那么聚合后的数据量在17000000
左右,比原表数据量大的多,构建这样的物化视图性能加速收益低。物化视图的聚合粒度要比查询细,即物化视图的聚合维度包含查询的聚合维度,这样才能提供查询所需的数据。查询可以不写
Group By
,同理,物化视图的聚合函数应该包含查询的聚合函数。 -
对于
Filter
如果查询中经常出现对相同字段的过滤,那么通过在物化视图中添加相应的
Filter
,可以减少物化视图中的数据量,从而提高查询时命中物化视图的性能。要注意的是,物化视图应该比查询中出现的
Filter
少,查询的Filter
要包含物化的Filter
。比如查询是a > 10 and b > 5
,物化视图可以没有Filter
,如果有Filter
的话应对a
和b
过滤,并且数据范围要求比查询大,例如物化视图可以是a > 5 and b > 5
,b > 0
,也可以是a > 5
等。 -
对于
Calculated Expressions
以
case when
、处理字符串等函数为例,这部分表达式计算非常消耗性能,如果在物化视图中能够提前计算好,透明改写使用计算好的物化视图则可以提高查询的性能。建议物化视图的列数量尽量不要过多。如果查询使用了多个字段,应该根据最开始的查询
SQL
模式分组,分别构建对应列的物化视图,避免单个物化视图的列过多。以聚合查询加速为例:
查询
1
:SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SELECT l_linestatus, sum( l_extendedprice * (1 - l_discount) ) AS revenue, o_shippriority FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey WHERE o_orderdate <= DATE '2024-06-30' AND o_orderdate >= DATE '2024-05-01' GROUP BY l_linestatus, o_shippriority, l_partkey;
查询
2
:SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SELECT l_linestatus, sum( l_extendedprice * (1 - l_discount) ) AS revenue, o_shippriority FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey WHERE o_orderdate <= DATE '2024-06-30' AND o_orderdate >= DATE '2024-05-01' GROUP BY l_linestatus, o_shippriority, l_suppkey;
根据以上两个
SQL
查询,我们可以构建一个更为通用的包含Aggregate
的物化视图。在这个物化视图中,我们将l_partkey
和l_suppkey
都作为聚合的group by
维度,并将o_orderdate
作为过滤条件。值得注意的是,o_orderdate
不仅在物化视图的条件补偿中使用,同时也需要被包含在物化视图的聚合group by
维度中。通过这种方式构建的物化视图后,查询
1
和查询2
都可以命中该物化视图,物化视图定义如下:SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
CREATE MATERIALIZED VIEW common_agg_mv BUILD IMMEDIATE REFRESH AUTO ON MANUAL DISTRIBUTED BY RANDOM BUCKETS 2 PROPERTIES ('replication_num' = '1') AS SELECT l_linestatus, sum( l_extendedprice * (1 - l_discount) ) AS revenue, o_shippriority, l_suppkey, l_partkey, o_orderdate FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey GROUP BY l_linestatus, o_shippriority, l_suppkey, l_partkey, o_orderdate;
6 使用场景¶
6.1 场景一:多表连接聚合查询加速¶
通过构建更通用的物化视图能够加速多表连接聚合查询。
以下面三个查询 SQL
为例:
查询 1
:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
查询 2
:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
查询 3
:
SQL | |
---|---|
1 2 3 4 5 6 7 8 |
|
对于如上查询,可以构建如下物化视图来满足上述所有查询。
物化视图的定义中去除了查询 1
和查询 2
的过滤条件,得到了一个更通用的 Join
,并提前计算了表达式 l_extendedprice * (1 - l_discount)
,这样当查询命中物化视图时,可以节省表达式的计算。
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
如果上述物化视图不能满足查询 2
的加速性能要求,可以构建聚合物化视图。为了保持通用性,可以去除对 o_orderdate
字段的过滤条件。
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
6.2 场景二:日志查询加速¶
在日志查询加速场景中,建议不局限于单独使用异步物化视图,可以结合同步物化视图。
一般基表是分区表,按照小时分区居多,单表聚合查询,一般过滤条件是按照时间,还有一些标识位。有时查询的响应速度无法达到要求,一般可以构建同步物化视图进行加速。
例如,基表的定义可能如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
物化视图可以按照分钟聚合数据,这样也能达到一定的聚合效果。例如:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
查询语句可能如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
6.3 场景三:湖仓一体联邦数据查询¶
很多用户有基于 Doris
进行联邦数据查询的需求, Doris
的多源数据目录( Multi-Catalog
)功能使得这一需求变得十分便捷。用户只需创建一个 Catalog
,无需将数据迁移到 Doris
,即可通过 Doris
对外部数据进行查询。
然而,这种方式也可能带来一些问题。因为查询外部数据的速度可能会受到网络及第三方服务的影响,导致响应速度较慢,对于响应速度要求比较高的场景,可能难以满足需求。
为了解决这个问题,可以基于外部 Catalog
创建异步物化视图。由于物化视图本身的数据是存储在 Doris
内部的,所以查询物化视图的速度会很快。因此,对于响应速度要求比较高的场景,我们可以考虑基于外部 Catalog
创建一个物化视图。
Tip
在湖仓一体场景下,使用外表透明改写之前需要打开 materialized_view_rewrite_enable_contain_external_table
开关,详情可参考异步物化视图功能描述。
6.4 场景四:数据建模(ETL)¶
有时用户会使用事实表和维度表加工成一张汇总表,之后对此汇总表进行 Ad-hoc
查询。此汇总表也可作为基础指标表,用于后续的建模。
此时,可以利用物化视图对基表的数据进行建模。之后,还可以利用创建好的物化视图创建更高层级的物化视图( 2.1.3
支持),灵活满足不同的需求。
不同层级的物化视图都可以自己设置刷新方式,例如:
-
第一层的物化视图可以设置为定时刷新,第二层的设置为触发刷新。这样,第一层的物化视图刷新完成后,会自动触发第二层物化视图的刷新。
-
如果每层的物化视图都设置为定时刷新,那么第二层物化视图刷新的时候,不会考虑第一层的物化视图数据是否和基表同步,只会把第一层物化视图的数据加工后同步到第二层。