当前位置: 首页 > news >正文

doris:最佳实践

异步物化视图使用原则​

  • 时效性考虑: 异步物化视图通常用于对数据时效性要求不高的场景,一般是 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 INTO lineitem VALUES      
(1, 2, 3, 4, '2024-05-01 01:45:05', 5.5, 6.5, 0.1, 8.5, 'o', 'k', '2024-05-01', '2024-05-01', '2024-05-01', 'a', 'b', 'yyyyyyyyy'),    
(1, 2, 3, 4, '2024-05-15 02:35:05', 5.5, 6.5, 0.15, 8.5, 'o', 'k', '2024-05-15', '2024-05-15', '2024-05-15', 'a', 'b', 'yyyyyyyyy'),     
(2, 2, 3, 5, '2024-05-25 08:30:06', 5.5, 6.5, 0.2, 8.5, 'o', 'k', '2024-05-25', '2024-05-25', '2024-05-25', 'a', 'b', 'yyyyyyyyy'),     
(3, 4, 3, 6, '2024-06-02 09:25:07', 5.5, 6.5, 0.3, 8.5, 'o', 'k', '2024-06-02', '2024-06-02', '2024-06-02', 'a', 'b', 'yyyyyyyyy'),     
(4, 4, 3, 7, '2024-06-15 13:20:09', 5.5, 6.5, 0, 8.5, 'o', 'k', '2024-06-15', '2024-06-15', '2024-06-15', 'a', 'b', 'yyyyyyyyy'),     
(5, 5, 6, 8, '2024-06-25 15:15:36', 5.5, 6.5, 0.12, 8.5, 'o', 'k', '2024-06-25', '2024-06-25', '2024-06-25', 'a', 'b', 'yyyyyyyyy'),     
(5, 5, 6, 9, '2024-06-29 21:10:52', 5.5, 6.5, 0.1, 8.5, 'o', 'k', '2024-06-30', '2024-06-30', '2024-06-30', 'a', 'b', 'yyyyyyyyy'),     
(5, 6, 5, 10, '2024-06-03 22:05:50', 7.5, 8.5, 0.1, 10.5, 'k', 'o', '2024-06-03', '2024-06-03', '2024-06-03', 'c', 'd', 'xxxxxxxxx');     CREATE TABLE IF NOT EXISTS partsupp (ps_partkey INTEGER NOT NULL, ps_suppkey INTEGER NOT NULL, ps_availqty INTEGER NOT NULL, ps_supplycost DECIMALV3(15, 2) NOT NULL, ps_comment VARCHAR(199) NOT NULL)
DUPLICATE KEY(ps_partkey, ps_suppkey)
DISTRIBUTED BY HASH(ps_partkey) BUCKETS 3;INSERT INTO partsupp VALUES     
(2, 3, 9, 10.01, 'supply1'),     
(4, 3, 9, 10.01, 'supply2'),     
(5, 6, 9, 10.01, 'supply3'),     
(6, 5, 10, 11.01, 'supply4');

在这个例子中,orders表的o_ordertime字段是分区字段,类型是DATETIME,按照天分区。

查询主要是按照"天"的粒度

SELECT l_linestatus, sum(l_extendedprice * (1 - l_discount)) AS revenue, ps_partkey 
FROM lineitem LEFT JOIN partsupp ON l_partkey = ps_partkey and l_suppkey = ps_suppkey 
WHERE date_trunc(l_ordertime, 'day') <= DATE '2024-05-25' AND date_trunc(l_ordertime, 'day') >= DATE '2024-05-05' 
GROUP BY l_linestatus, ps_partkey;

为了不让物化视图每次刷新的分区数量过多,物化视图的分区粒度可以和基表orders一致,也按"天"分区。

物化视图的定义 SQL 的粒度可以按照"天",并且按照"天"来聚合数据,

CREATE MATERIALIZED VIEW rollup_partition_mv 
BUILD IMMEDIATE REFRESH AUTO ON MANUAL 
partition by(order_date) 
DISTRIBUTED BY RANDOM BUCKETS 2 
AS 
SELECT l_linestatus, sum(l_extendedprice * (1 - l_discount)) AS revenue, ps_partkey, date_trunc(l_ordertime, 'day') as order_date 
FROM lineitem LEFT JOIN partsupp ON l_partkey = ps_partkey and l_suppkey = ps_suppkey 
GROUP BY l_linestatus, ps_partkey, date_trunc(l_ordertime, 'day');

如何使用物化视图加速查询​

使用物化视图查询加速,首先需要查看 profile 文件,找到一个查询消耗时间最多的操作,一般出现在连接(Join)、聚合(Aggregate)、过滤(Filter)或者表达式计算(Calculated Expressions)。

对于 Join、Aggregate、Filters、Calculated Expressions,构建物化视图都能起到加速查询的作用。如果一个查询中 Join 占用了大量的计算资源,而 Aggregate 相对而言占用较小的资源,则可以针对 Join 构建物化视图。

接下来,将详细说明如何针对上述四种操作构建物化视图:

1. 对于 Join

可以提取查询中使用的公共的表连接模式来构建物化视图。透明改写如果使用了此物化视图,可以节省 Join 连接的计算。将查询中的 Filters 去除,这样就是一个比较通用的 Join 物化视图。

2. 对于 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,同理,物化视图的聚合函数应该包含查询的聚合函数。

3. 对于 Filter

如果查询中经常出现对相同字段的过滤,那么通过在物化视图中添加相应的 Filter,可以减少物化视图中的数据量,从而提高查询时命中物化视图的性能。

要注意的是,物化视图应该比查询中出现的 Filter 少,查询的 Filter 要包含物化的 Filter。比如查询是 a > 10 and b > 5,物化视图可以没有 Filter,如果有 Filter 的话应对 a 和 b 过滤,并且数据范围要求比查询大,例如物化视图可以是 a > 5 and b > 5,b > 0,也可以是 a > 5 等。

4. 对于 Calculated Expressions

以 case when、处理字符串等函数为例,这部分表达式计算非常消耗性能,如果在物化视图中能够提前计算好,透明改写使用计算好的物化视图则可以提高查询的性能。

建议物化视图的列数量尽量不要过多。如果查询使用了多个字段,应该根据最开始的查询 SQL 模式分组,分别构建对应列的物化视图,避免单个物化视图的列过多。

以聚合查询加速为例:

查询 1:

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:

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 都可以命中该物化视图,物化视图定义如下:

CREATE MATERIALIZED VIEW common_agg_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 2
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;

使用场景​

场景一:查询加速​

在 BI 报表场景或其他加速场景中,用户对于查询响应时间较为敏感,通常要求能够秒级别返回结果。而查询通常涉及多张表先进行 Join 计算、再聚合计算, 该过程会消耗大量计算资源,并且有时难以保证时效性。对此,异步物化视图能够很好应对,它不仅支持直接查询,也支持透明改写, 优化器会依据改写算法和代价模型,自动选择最优的物化视图来响应请求。

用例 1 多表连接聚合查询加速​

通过构建更通用的物化视图能够加速多表连接聚合查询。

以下面三个查询 SQL 为例:

查询 1:

SELECT l_linestatus, l_extendedprice * (1 - l_discount)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';

查询 2:

SELECT l_linestatus, sum(l_extendedprice * (1 - l_discount)) AS revenue, o_orderdate, 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_orderdate, o_shippriority;

查询 3:

SELECT l_linestatus, l_extendedprice * (1 - l_discount),o_orderdate, o_shippriority 
FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey;

对于如上查询,可以构建如下物化视图来满足上述所有查询。

物化视图的定义中去除了查询 1 和查询 2 的过滤条件,得到了一个更通用的 Join,并提前计算了表达式l_extendedprice * (1 - l_discount),这样当查询命中物化视图时,可以节省表达式的计算。

CREATE MATERIALIZED VIEW common_join_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 2
AS 
SELECT l_linestatus, l_extendedprice * (1 - l_discount),o_orderdate, o_shippriority 
FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey;

如果上述物化视图不能满足查询 2 的加速性能要求,可以构建聚合物化视图。为了保持通用性,可以去除对o_orderdate字段的过滤条件。

CREATE MATERIALIZED VIEW target_agg_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 2
AS 
SELECT l_linestatus, sum(l_extendedprice * (1 - l_discount)) AS revenue, o_orderdate, o_shippriority 
FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey 
GROUP BY l_linestatus, o_orderdate, o_shippriority;

用例 2 日志查询加速​

在日志查询加速场景中,建议不局限于单独使用异步物化视图,可以结合同步物化视图。

一般基表是分区表,按照小时分区居多,单表聚合查询,一般过滤条件是按照时间,还有一些标识位。有时查询的响应速度无法达到要求,一般可以构建同步物化视图进行加速。

例如,基表的定义可能如下:

CREATE TABLE IF NOT EXISTS test (
`app_name` VARCHAR(64) NULL COMMENT '标识', 
`event_id` VARCHAR(128) NULL COMMENT '标识', 
`decision` VARCHAR(32) NULL COMMENT '枚举值', 
`time` DATETIME NULL COMMENT '查询时间', 
`id` VARCHAR(35) NOT NULL COMMENT 'od', 
`code` VARCHAR(64) NULL COMMENT '标识', 
`event_type` VARCHAR(32) NULL COMMENT '事件类型' 
)
DUPLICATE KEY(app_name, event_id)
PARTITION BY RANGE(time)                                    
(                                                                                                                                      FROM ("2024-07-01 00:00:00") TO ("2024-07-15 00:00:00") INTERVAL 1 HOUR                                                                     
)     
DISTRIBUTED BY HASH(event_id)
BUCKETS 3;

物化视图可以按照分钟聚合数据,这样也能达到一定的聚合效果。例如:

CREATE MATERIALIZED VIEW sync_mvASSELECT decision,code, app_name, event_id, event_type, date_trunc(time, 'minute'), DATE_FORMAT(`time`, '%Y-%m-%d'), cast(FLOOR(MINUTE(time) / 15) as decimal(9, 0)),count(id) as cntfrom test group by code, app_name, event_id, event_type, date_trunc(time, 'minute'), decision, DATE_FORMAT(time, '%Y-%m-%d'), cast(FLOOR(MINUTE(`time`) / 15) as decimal(9, 0));

查询语句可能如下:

SELECT decision, CONCAT(CONCAT(DATE_FORMAT(`time`, '%Y-%m-%d'), '', LPAD(cast(FLOOR(MINUTE(`time`) / 15) as decimal(9, 0)) * 15, 5, '00'), ':00')) as time, count(id) as cnt from test where date_trunc(time, 'minute') BETWEEN '2024-07-02 18:00:00' AND '2024-07-03 20:00:00' group by decision, DATE_FORMAT(`time`, "%Y-%m-%d"), cast(FLOOR(MINUTE(`time`) / 15) as decimal(9, 0));

场景二:数据建模(ETL)​

数据分析工作往往需要对多表进行连接和聚合,这一过程通常涉及复杂且频繁重复的查询。 这类查询可能引发查询延迟高或资源消耗大的问题。然而,如果采用异步物化视图构建数据分层模型,则可以很好避免该问题, 利用创建好的物化视图创建更高层级的物化视图(2.1.3 支持),灵活满足不同的需求。

不同层级的物化视图可以设置各自的触发方式,例如:

  • 第一层的物化视图可以设置为定时刷新,第二层的设置为触发刷新。这样,第一层的物化视图刷新完成后,会自动触发第二层物化视图的刷新。
  • 如果每层的物化视图都设置为定时刷新,那么第二层物化视图刷新的时候,不会考虑第一层的物化视图数据是否和基表同步,只会把第一层物化视图的数据加工后同步到第二层。

接下来,通过 TPC-H 数据集说明异步物化视图在数据建模中的应用,以分析每月各地区和国家的订单数量和利润为例:

原始查询(未使用物化视图):

SELECT
n_name,
date_trunc(o.o_orderdate, 'month') as month,
count(distinct o.o_orderkey) as order_count,
sum(l.l_extendedprice * (1 - l.l_discount)) as revenue
FROM orders o
JOIN lineitem l ON o.o_orderkey = l.l_orderkey
JOIN customer c ON o.o_custkey = c.c_custkey
JOIN nation n ON c.c_nationkey = n.n_nationkey
JOIN region r ON n.n_regionkey = r.r_regionkey
GROUP BY n_name, month;

使用异步物化视图分层建模:

构建 DWD 层(明细数据),处理订单明细宽表

CREATE MATERIALIZED VIEW dwd_order_detail
BUILD IMMEDIATE REFRESH AUTO ON COMMIT
DISTRIBUTED BY RANDOM BUCKETS 16
AS
select
o.o_orderkey,
o.o_custkey,
o.o_orderstatus,
o.o_totalprice,
o.o_orderdate,
c.c_name,
c.c_nationkey,
n.n_name as nation_name,
r.r_name as region_name,
l.l_partkey,
l.l_quantity,
l.l_extendedprice,
l.l_discount,
l.l_tax
from orders o
join customer c on o.o_custkey = c.c_custkey
join nation n on c.c_nationkey = n.n_nationkey
join region r on n.n_regionkey = r.r_regionkey
join lineitem l on o.o_orderkey = l.l_orderkey;

构建 DWS 层(汇总数据),进行每日订单汇总

CREATE MATERIALIZED VIEW dws_daily_sales
BUILD IMMEDIATE REFRESH AUTO ON COMMIT
DISTRIBUTED BY RANDOM BUCKETS 16
AS
select
date_trunc(o_orderdate, 'month') as month,
nation_name,
region_name,
bitmap_union(to_bitmap(o_orderkey)) as order_count,
sum(l_extendedprice * (1 - l_discount)) as net_revenue
from dwd_order_detail
group by
date_trunc(o_orderdate, 'month'),
nation_name,
region_name;

使用物化视图优化查询如下:

SELECT
nation_name,
month,
bitmap_union_count(order_count),
sum(net_revenue) as revenue
FROM dws_daily_sales
GROUP BY nation_name, month;

场景三:湖仓一体联邦数据查询​

在现代化的数据架构中,企业通常会采用湖仓一体设计,以平衡数据的存储成本与查询性能。在这种架构下,经常会遇到两个关键挑战:

  • 查询性能受限:频繁查询数据湖中的数据时,可能会受到网络延迟和第三方服务的影响,从而导致查询延迟,进而影响用户体验。
  • 数据分层建模的复杂性:在数据湖到实时数仓的数据流转和转换过程中,通常需要复杂的 ETL 流程,这增加了维护成本和开发难度

使用 Doris 异步物化视图,可以很好的应对上述挑战:

  • 透明改写加速查询:将常用的数据湖查询结果物化到 Doris 内部存储,采用透明改写可有效提升查询性能。
  • 简化分层建模:支持基于数据湖中的表创建物化视图,实现从数据湖到实时数仓的便捷转换,极大简化了数据建模流程。

如下,以 Hive 示例说明:

基于 Hive 创建 Catalog,使用 TPC-H 数据集

CREATE CATALOG hive_catalog PROPERTIES (
'type'='hms', -- hive meta store 地址
'hive.metastore.uris' = 'thrift://172.21.0.1:7004'
);

基于 Hive Catalog 创建物化视图

-- 物化视图只能在 internal 的 catalog 上创建,切换到内部 catalog
switch internal;
create database hive_mv_db;
use hive_mv_db;CREATE MATERIALIZED VIEW external_hive_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 12
AS
SELECT
n_name,
o_orderdate,
sum(l_extendedprice * (1 - l_discount)) AS revenue
FROM
customer,
orders,
lineitem,
supplier,
nation,
region
WHERE
c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND l_suppkey = s_suppkey
AND c_nationkey = s_nationkey
AND s_nationkey = n_nationkey
AND n_regionkey = r_regionkey
AND r_name = 'ASIA'
GROUP BY
n_name,
o_orderdate;

运行如下的查询,通过透明改写自动使用物化视图加速查询。

SELECT
n_name,
sum(l_extendedprice * (1 - l_discount)) AS revenue
FROM
customer,
orders,
lineitem,
supplier,
nation,
region
WHERE
c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND l_suppkey = s_suppkey
AND c_nationkey = s_nationkey
AND s_nationkey = n_nationkey
AND n_regionkey = r_regionkey
AND r_name = 'ASIA'
AND o_orderdate >= DATE '1994-01-01'
AND o_orderdate < DATE '1994-01-01' + INTERVAL '1' YEAR
GROUP BY
n_name
ORDER BY
revenue DESC;

提示

Doris 暂无法感知除 Hive 外的其他外表数据变更。当外表数据不一致时,使用物化视图可能出现数据不一致的情况。以下开关表示:参与透明改写的物化视图是否允许包含外表,默认 false。如接受数据不一致或者通过定时刷新来保证外表数据一致性,可以将此开关设置成 true。 设置包含外表的物化视图是否可用于透明改写,默认不允许,如果可以接受数据不一致或者可以自行保证数据一致,可以开启

SET materialized_view_rewrite_enable_contain_external_table = true;

如果物化视图在 MaterializedViewRewriteSuccessButNotChose 状态,说明改写成功但 plan 未被 CBO 选择,可能是因为外表的统计信息不完整。 启用统计信息从文件中获取行数

SET enable_get_row_count_from_file_list = true;

查看外表统计信息,确认是否已收集完整

SHOW TABLE STATS external_table_name;

自 2.1.3 版本支持创建物化视图的定义 SQL 使用物化视图,即嵌套物化视图。

场景四:提升写入效率,减少资源竞争​

在高吞吐的数据写入的场景中,系统性能的稳定性与数据处理的高效性同样重要。通过异步物化视图灵活的刷新策略,用户可以根据具体场景选择合适的刷新方式, 从而降低写入压力,避免资源争抢。

相比之下,异步物化视图提供了手动触发、触发式、周期性触发三种灵活的刷新策略。用户可以根据场景需求差异,选择合适的刷新策略。当基表数据变更时,不会立即触发物化视图刷新,延迟刷新有利于降低资源压力,有效避免写入资源争抢。

如下所示,选择的刷新方式为定时刷新,每 2 小时刷新一次。当 orders 和 lineitem 导入数据时,不会立即触发物化视图刷新。

CREATE MATERIALIZED VIEW common_schedule_join_mv
BUILD IMMEDIATE REFRESH AUTO ON SCHEDULE EVERY 2 HOUR
DISTRIBUTED BY RANDOM BUCKETS 16
AS
SELECT
l_linestatus,
l_extendedprice * (1 - l_discount),
o_orderdate,
o_shippriority
FROM
orders
LEFT JOIN lineitem ON l_orderkey = o_orderkey;

透明改写能够对查询 SQL 的改写,实现了查询加速,同时也能对导入 SQL 进行改写,从而提升导入效率。 从 2.1.6 版本开始,当物化视图和基表数据强一致时,可对 DML 操作如 Insert Into 或者 Insert Overwrite 进行透明改写,这对于数据导入场景的性能提升有显著效果。

  1. 创建 Insert Into 数据的目标表
CREATE TABLE IF NOT EXISTS target_table  (
orderdate      DATE NOT NULL,
shippriority   INTEGER NOT NULL,
linestatus     CHAR(1) NOT NULL,
sale           DECIMALV3(15,2) NOT NULL
)
DUPLICATE KEY(orderdate, shippriority)
DISTRIBUTED BY HASH(shippriority) BUCKETS 3;

  1. common_schedule_join_mv
CREATE MATERIALIZED VIEW common_schedule_join_mv
BUILD IMMEDIATE REFRESH AUTO ON SCHEDULE EVERY 2 HOUR
DISTRIBUTED BY RANDOM BUCKETS 16
AS
SELECT
l_linestatus,
l_extendedprice * (1 - l_discount),
o_orderdate,
o_shippriority
FROM
orders
LEFT JOIN lineitem ON l_orderkey = o_orderkey;

未经改写的导入语句如下:

INSERT INTO target_table
SELECT
o_orderdate,
o_shippriority,
l_linestatus,
l_extendedprice * (1 - l_discount)
FROM
orders
LEFT JOIN lineitem ON l_orderkey = o_orderkey;

经过透明改写后,语句如下:

INSERT INTO target_table
SELECT *
FROM common_schedule_join_mv;

需要注意的是:如果 DML 操作的是无法感知数据变更的外表,透明改写可能导致基表最新数据无法实时导入目标表。如果用户可以接受数据不一致或能够自行保证数据一致性,可以打开如下开关

DML 时,当物化视图存在无法实时感知数据的外表时,是否开启基于结构信息的物化视图透明改写,默认关闭

SET enable_dml_materialized_view_rewrite_when_base_table_unawareness = true;

相关文章:

doris:最佳实践

异步物化视图使用原则​ 时效性考虑&#xff1a; 异步物化视图通常用于对数据时效性要求不高的场景&#xff0c;一般是 T1 的数据。如果时效性要求高&#xff0c;应考虑使用同步物化视图。 加速效果与一致性考虑&#xff1a; 在查询加速场景&#xff0c;创建物化视图时&#x…...

[创业之路-299]:图解金融体系结构

一、金融体系结构 1.1 概述 金融体系结构是一个国家以行政的、法律的形式和运用经济规律确定的金融系统结构&#xff0c;以及构成这个系统的各种类型的银行和非银行金融机构的职能作用和相互关系。以下是对金融体系结构的详细分析&#xff1a; 1、金融体系的构成要素 现代金…...

RL--2

强化学习当中最难的两个点是&#xff1a; 1.reward delay&#xff1b; 2.agent的行为会影响到之后看到的东西&#xff0c;所以agent要学会探索世界&#xff1b; 关于强化学习的不同类型&#xff0c;可以分为以下三种&#xff1a; 一种是policy based&#xff1a;可以理解为它是…...

[JVM篇]分代垃圾回收

分代垃圾回收 分代收集法是目前大部分 JVM 所采用的方法&#xff0c;其核心思想是根据对象存活的不同生命周期将内存划分为不同的域&#xff0c;一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象…...

Dify本地安装

目录 方式一docker安装&#xff1a; 方式二源码安装&#xff1a; Dify本地安装可以用docker方式&#xff0c;和源码编译方式。 先到云厂商平台申请一台Centos系统云主机&#xff0c;网络选择海外&#xff0c;需要公网IP&#xff0c;再按一下流程操作&#xff1a; 方式一doc…...

python | 两招解决第三方库安装难点

前言 python 被广泛应用的原因之一&#xff0c;便是拥有大量的第三方库&#xff0c;涵盖 web 开发、数据分析和机器学习等多个方面。 对于多数初学者来说&#xff0c;如何成功安装 python 第三方库成为了一大难点&#xff0c;总是因各种原因导致安装失败。 本文以自身经验&a…...

stm32mp15x 之 M4 使用 canfd

目录 序配置添加注坑参考 序 在使用 stm32mp15x 系列时&#xff0c;M4 有不少的坑&#xff0c;这里简单聊聊使用 canfd 时遇到的一些问题。 配置 这里使用 PLL4R 为 100M&#xff0c;用于 CANFD 的时钟 canfd 速率配置成 1M &#xff0c;5M&#xff0c;其中数据传输速率为 5M…...

第七天:数据提取-正则表达式

每天上午9点左右更新一到两篇文章到专栏《Python爬虫训练营》中&#xff0c;对于爬虫有兴趣的伙伴可以订阅专栏一起学习&#xff0c;完全免费。 键盘为桨&#xff0c;代码作帆。这趟为期30天左右的Python爬虫特训即将启航&#xff0c;每日解锁新海域&#xff1a;从Requests库的…...

Python入门全攻略(六)

文件操作 文件路径 绝对路径:D:\pythonLearing\fileOperating.exe 相对路径:./fileOperating.exe # ./表示当前目录 # ../表示上一级目录 字符编码 字符集编码说明ASCll 最早的字符编码标准之一,基于拉丁字母的字符集,一共有128个字符GBK(国际码)用于简体中文的字符编码,…...

MongoDB副本集

副本集架构 对于mongodb来说&#xff0c;数据库高可用是通过副本集架构实现的&#xff0c;一个副本集由一个主节点和若干个从节点所组成。 客户端通过数据库主节点写入数据后&#xff0c;由从节点进行复制同步&#xff0c;这样所有从节点都会拥有这些业务数据的副本&#xff0…...

登录弹窗效果

1&#xff0c;要求 点击登录按钮&#xff0c;弹出登录窗口 提示1&#xff1a;登录窗口 display:none 隐藏状态&#xff1b; 提示2&#xff1a;登录按钮点击后&#xff0c;触发事件&#xff0c;修改 display:block 显示状态 提示3&#xff1a;登录窗口中点击关闭按钮&#xff0…...

C++上机_日期问题

1.求下一天的年月日 问题 已知某天的年月日&#xff0c;求下一天的年月日。 思路 参数&#xff1a;年&#xff0c;月&#xff0c;日&#xff08;int) 返回值&#xff1a;void 处理&#xff1a;根据参数所给年月日&#xff0c;求下一天的年月日 思路: 1、定义一个数组&a…...

应对DeepSeek总是服务器繁忙的解决方法

最近由于访问量过大&#xff0c;DeepSeek服务器官网经常弹出&#xff1a;“服务器繁忙&#xff0c;请稍后再试”的提示&#xff0c;直接卡成PPT怎么办&#xff1f;服务器繁忙直接看到视觉疲劳&#xff1a; 解决DeepSeek卡顿问题 DeepSeek使用卡顿问题&#xff0c;是因为访问量…...

web第三次作业

弹窗案例 1.首页代码 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>综合案例</title><st…...

力扣 438.找到字符串中所有字母异位词

题目&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cb…...

【Python】Python入门——基础语法及顺序语句

Python入门——基础语法及顺序语句 官方文档地址&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.htmlPython 是一门易于学习、功能强大的编程语言。它提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。Python 优雅的语法和动态类型以及解释型语…...

2.2 反向传播:神经网络如何“学习“?

一、神经网络就像小学生 想象一个刚学算术的小学生&#xff0c;老师每天布置练习题&#xff0c;学生根据例题尝试解题&#xff0c;老师批改后指出错误。神经网络的学习过程与此相似&#xff1a; 输入层&#xff1a;相当于练习题&#xff08;如数字图片&#xff09;输出层&…...

frp-tool,客户端frp命令行工具

在日常开发和运维过程中&#xff0c;端口转发和配置管理是常见的需求。 如果有自己一台服务器&#xff0c;并且已经开放好端口&#xff0c;配置好token后&#xff0c;这个工具一定能帮到你。 今天给大家推荐一款非常好用的frpc命令行工具&#xff0c;它是一个用Python编写的命令…...

【学术投稿-第五届应用数学、建模与智能计算国际学术会议】CSS伪类选择器深度解析:分类、应用与技巧

大会官网&#xff1a;www.cammic.org 大会时间&#xff1a;2025年3月21-23日 大会地点&#xff1a;中国-上海&#xff08;上海大学宝山校区北大门乐乎新楼&#xff09; 简介 第五届应用数学、建模与智能计算&#xff08;CAMMIC 2025&#xff09;将于2025年3月21-23日在中国…...

常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二叉树查找、红黑树查找、B树和B+树查找、分块查找)

常用的查找算法&#xff1a; 顺序查找&#xff1a;最简单的查找算法&#xff0c;适用于无序或数据量小的情况&#xff0c;逐个元素比较查找目标值。二分查找&#xff1a;要求数据有序&#xff0c;通过不断比较中间元素与目标值&#xff0c;将查找范围缩小一半&#xff0c;效率…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...