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 进行透明改写,这对于数据导入场景的性能提升有显著效果。
- 创建 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;
- 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:最佳实践
异步物化视图使用原则 时效性考虑: 异步物化视图通常用于对数据时效性要求不高的场景,一般是 T1 的数据。如果时效性要求高,应考虑使用同步物化视图。 加速效果与一致性考虑: 在查询加速场景,创建物化视图时&#x…...
[创业之路-299]:图解金融体系结构
一、金融体系结构 1.1 概述 金融体系结构是一个国家以行政的、法律的形式和运用经济规律确定的金融系统结构,以及构成这个系统的各种类型的银行和非银行金融机构的职能作用和相互关系。以下是对金融体系结构的详细分析: 1、金融体系的构成要素 现代金…...
RL--2
强化学习当中最难的两个点是: 1.reward delay; 2.agent的行为会影响到之后看到的东西,所以agent要学会探索世界; 关于强化学习的不同类型,可以分为以下三种: 一种是policy based:可以理解为它是…...
[JVM篇]分代垃圾回收
分代垃圾回收 分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象…...
Dify本地安装
目录 方式一docker安装: 方式二源码安装: Dify本地安装可以用docker方式,和源码编译方式。 先到云厂商平台申请一台Centos系统云主机,网络选择海外,需要公网IP,再按一下流程操作: 方式一doc…...
python | 两招解决第三方库安装难点
前言 python 被广泛应用的原因之一,便是拥有大量的第三方库,涵盖 web 开发、数据分析和机器学习等多个方面。 对于多数初学者来说,如何成功安装 python 第三方库成为了一大难点,总是因各种原因导致安装失败。 本文以自身经验&a…...
stm32mp15x 之 M4 使用 canfd
目录 序配置添加注坑参考 序 在使用 stm32mp15x 系列时,M4 有不少的坑,这里简单聊聊使用 canfd 时遇到的一些问题。 配置 这里使用 PLL4R 为 100M,用于 CANFD 的时钟 canfd 速率配置成 1M ,5M,其中数据传输速率为 5M…...
第七天:数据提取-正则表达式
每天上午9点左右更新一到两篇文章到专栏《Python爬虫训练营》中,对于爬虫有兴趣的伙伴可以订阅专栏一起学习,完全免费。 键盘为桨,代码作帆。这趟为期30天左右的Python爬虫特训即将启航,每日解锁新海域:从Requests库的…...
Python入门全攻略(六)
文件操作 文件路径 绝对路径:D:\pythonLearing\fileOperating.exe 相对路径:./fileOperating.exe # ./表示当前目录 # ../表示上一级目录 字符编码 字符集编码说明ASCll 最早的字符编码标准之一,基于拉丁字母的字符集,一共有128个字符GBK(国际码)用于简体中文的字符编码,…...
MongoDB副本集
副本集架构 对于mongodb来说,数据库高可用是通过副本集架构实现的,一个副本集由一个主节点和若干个从节点所组成。 客户端通过数据库主节点写入数据后,由从节点进行复制同步,这样所有从节点都会拥有这些业务数据的副本࿰…...
登录弹窗效果
1,要求 点击登录按钮,弹出登录窗口 提示1:登录窗口 display:none 隐藏状态; 提示2:登录按钮点击后,触发事件,修改 display:block 显示状态 提示3:登录窗口中点击关闭按钮࿰…...
C++上机_日期问题
1.求下一天的年月日 问题 已知某天的年月日,求下一天的年月日。 思路 参数:年,月,日(int) 返回值:void 处理:根据参数所给年月日,求下一天的年月日 思路: 1、定义一个数组&a…...
应对DeepSeek总是服务器繁忙的解决方法
最近由于访问量过大,DeepSeek服务器官网经常弹出:“服务器繁忙,请稍后再试”的提示,直接卡成PPT怎么办?服务器繁忙直接看到视觉疲劳: 解决DeepSeek卡顿问题 DeepSeek使用卡顿问题,是因为访问量…...
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.找到字符串中所有字母异位词
题目: 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cb…...
【Python】Python入门——基础语法及顺序语句
Python入门——基础语法及顺序语句 官方文档地址:https://docs.python.org/zh-cn/3/tutorial/index.htmlPython 是一门易于学习、功能强大的编程语言。它提供了高效的高级数据结构,还能简单有效地面向对象编程。Python 优雅的语法和动态类型以及解释型语…...
2.2 反向传播:神经网络如何“学习“?
一、神经网络就像小学生 想象一个刚学算术的小学生,老师每天布置练习题,学生根据例题尝试解题,老师批改后指出错误。神经网络的学习过程与此相似: 输入层:相当于练习题(如数字图片)输出层&…...
frp-tool,客户端frp命令行工具
在日常开发和运维过程中,端口转发和配置管理是常见的需求。 如果有自己一台服务器,并且已经开放好端口,配置好token后,这个工具一定能帮到你。 今天给大家推荐一款非常好用的frpc命令行工具,它是一个用Python编写的命令…...
【学术投稿-第五届应用数学、建模与智能计算国际学术会议】CSS伪类选择器深度解析:分类、应用与技巧
大会官网:www.cammic.org 大会时间:2025年3月21-23日 大会地点:中国-上海(上海大学宝山校区北大门乐乎新楼) 简介 第五届应用数学、建模与智能计算(CAMMIC 2025)将于2025年3月21-23日在中国…...
常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二叉树查找、红黑树查找、B树和B+树查找、分块查找)
常用的查找算法: 顺序查找:最简单的查找算法,适用于无序或数据量小的情况,逐个元素比较查找目标值。二分查找:要求数据有序,通过不断比较中间元素与目标值,将查找范围缩小一半,效率…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
