异步物化视图使用原则
-
时效性考虑: 异步物化视图通常用于对数据时效性要求不高的场景,一般是 T+1 的数据。如果时效性要求高,应考虑使用同步物化视图。
-
加速效果与一致性考虑: 在查询加速场景,创建物化视图时,DBA 应将常见查询 SQL 模式分组,尽量使组之间无重合。SQL 模式组划分越清晰,物化视图构建的质量越高。一个查询可能使用多个物化视图,同时一个物化视图也可能被多个查询使用。构建物化视图需要综合考虑命中物化视图的响应时间(加速效果)、构建成本、数据一致性要求等。
-
物化视图定义与构建成本考虑:
-
物化视图定义和原查询越接近,查询加速效果越好,但物化的通用性和复用性越差,意味着构建成本越高。
-
物化视图定义越通用(例如没有 WHERE 条件和更多聚合维度),查询加速效果较低,但物化的通用性和复用性越好,意味着构建成本越低。
-
注意
-
物化视图数量控制: 物化视图并非越多越好。物化视图构建和刷新需要资源。物化视图参与透明改写,CBO 代价模型选择最优物化视图需要时间。理论上,物化视图越多,透明改写的时间越长。
-
定期检查物化视图使用状态: 如果未使用,应及时删除。
-
基表数据更新频率: 如果物化视图的基表数据频繁更新,可能不太适合使用物化视图,因为这会导致物化视图频繁失效,不能用于透明改写(可直查)。如果需要使用此类物化视图进行透明改写,需要允许查询的数据有一定的时效延迟,并可以设定
grace_period
。具体见grace_period
的适用介绍。
物化视图刷新方式选择原则
当满足以下条件时,建议创建分区物化视图:
-
物化视图的基表数据量很大,并且基表是分区表。
-
物化视图使用的表除了分区表外,其他表不经常变化。
-
物化视图的定义 SQL 和分区字段满足分区推导的要求,即符合分区增量更新的要求。详细要求可参考:CREATE-ASYNC-MATERIALIZED-VIEW
-
物化视图分区数不多,分区过多会导致分区多物化视图构建时间会过长。
当物化视图的部分分区失效时,透明改写可以使用物化视图的有效分区 UNION ALL 基表返回数据。
如果不能构建分区物化视图,可以考虑选择全量刷新的物化视图。
分区物化视图常见使用方式
当物化视图的基表数据量很大,且基表是分区表时,如果物化视图的定义 SQL 和分区字段满足分区推导的要求,此种场景比较适合构建分区物化视图。分区推导的详细要求可参考 CREATE-ASYNC-MATERIALIZED-VIEW 和异步物化视图 FAQ 构建问题 12。
物化视图的分区是跟随基表的分区映射创建的,一般和基表的分区是 1:1 或者 1:n 的关系。
-
如果基表的分区发生数据变更,如新增分区、删除分区等情况,物化视图对应的分区也会失效。失效的分区不能用于透明改写,但可以直查。透明改写时发现物化视图的分区数据失效,失效的分区会通过联合基表来响应查询。
确认物化视图分区状态的命令详见查看物化视图状态,主要是
show partitions from mv_name
命令。 -
如果物化视图引用的非分区表发生数据变更,会触发物化视图所有分区失效,导致此物化视图不能用于透明改写。需要刷新物化视图所有分区的数据,命令为
REFRESH MATERIALIZED VIEW mv1 AUTO;
。此命令会尝试刷新物化视图所有数据变化的分区。因此,一般将数据频繁变化的表放在分区物化视图引用的分区表,将不经常变化的维表放在非引用分区表的位置。
-
如果物化视图引用的非分区表发生数据变更,非分区表数据只是新增,不涉及修改,创建物化视图的时候可以指定属性
excluded_trigger_tables = '非分区表名1,非分区表名2'
,这样非分区表的数据变化就不会使物化视图的所有分区失效,下次刷新时,只刷新分区表对应的物化视图失效分区。
分区物化视图的透明改写是分区粒度的,即使物化视图的部分分区失效,此物化视图仍然可用于透明改写。但如果只查询了一个分区,并且物化视图这个分区数据失效了,那么此物化视图不能用于透明改写。
例如:
CREATE TABLE IF NOT EXISTS lineitem (
l_orderkey INTEGER NOT NULL,
l_partkey INTEGER NOT NULL,
l_suppkey INTEGER NOT NULL,
l_linenumber INTEGER NOT NULL,
l_ordertime DATETIME NOT NULL,
l_quantity DECIMALV3(15, 2) NOT NULL,
l_extendedprice DECIMALV3(15, 2) NOT NULL,
l_discount DECIMALV3(15, 2) NOT NULL,
l_tax DECIMALV3(15, 2) NOT NULL,
l_returnflag CHAR(1) NOT NULL,
l_linestatus CHAR(1) NOT NULL,
l_shipdate DATE NOT NULL,
l_commitdate DATE NOT NULL,
l_receiptdate DATE NOT NULL,
l_shipinstruct CHAR(25) NOT NULL,
l_shipmode CHAR(10) NOT NULL,
l_comment VARCHAR(44) NOT NULL
) DUPLICATE KEY(
l_orderkey, l_partkey, l_suppkey,
l_linenumber
) PARTITION BY RANGE(l_ordertime) (
FROM
('2024-05-01') TO ('2024-06-30') INTERVAL 1 DAY
)
DISTRIBUTED BY HASH(l_orderkey) BUCKETS 3;
INSERT I