You need to enable JavaScript to run this app.
导航
异步物化视图
最近更新时间:2024.08.29 12:45:15首次发布时间:2024.08.29 12:45:15

基本概念

  • 基表(Base Table)- 物化视图的驱动表, 异步物化视图支持join,subquery多表的关联查询。
  • 目的表(Target Table)- **** 物化视图实际存储的表,一般是AggregateMergeTree 或者MergeTree
  • 物化视图 (Materialized View) - 逻辑概念定义基表到目的表的映射关系
  • 刷新 (Refresh) - 创建物化视图后,其中的数据仅反映创建时刻基表的状态。当基表中的数据发生变化时,需要通过刷新通过视图从基表执行查询映射到目的表。
  • 查询改写(Query Rewrite)- 查询改写是指在对已构建了物化视图的基表进行查询时,系统自动判断是否可以复用物化视图中的预计算结果处理查询。如果可以复用,系统会直接从相关的物化视图读取预计算结果,以避免重复计算消耗系统资源和时间。

使用场景

当前开源ClickHouse的物化视图是同步视图,对于使用场景有如下限制:

  • 影响基表数据导入性能
  • 支持单表,无法支持多表关联

为了更好的支持多表关联的场景,减少对于数据导入影响,一个比较好的解决方法是使用异步视图,其用途主要包括:

  • 复杂查询加速: 异步物化视图存储了基于基表特定查询语句的预计算结果。对基表执行复杂查询时,可以直接复用预计算结果,避免重复计算,进而提高查询性能。查询的频率越高或查询语句越复杂,性能增益就会越很明显。
  • 数据加工:通过异步物化视图可以对底层数据进行ELT做轻量级的数据加工,直接在ClickHouse引擎内容实现数据的转化,减少在不同的数据处理系统切换,降低使用门槛和维护成本。

视图类型

单表聚合

多表关联

查询改写

刷新策略

数据导入影响

异步物化视图

异步刷新
手动刷新

同步物化视图

导入同步刷新

基本语法

CREATE MATERIALIZED VIEW [IF NOT EXISTS] [database.]<mv_name>
[REFRESH [ASYNC [START (start_time)] [EVERY INTERVAL refresh_interval] | SYNC | MANUAL]] AS <query_statement>;

SYSTEM [START VIEW | STOP VIEW] [database.]<mv_name>;

ALTER TABLE [database.]<mv_name> MODIFY REFRESH EVERY INTERVAL ... ;

REFRESH MATERIALIZED VIEW [database.]<mv_name>;

示例

以下是一个使用异步物化视图的使用示例。

CREATE DATABASE business;

-- 源数据表1
CREATE TABLE business.goods(
    create_date       DateTime,
    series_id         UInt64,
    goods_id          Int64,
    item_name         String,
    price             Float64
) ENGINE = CnchMergeTree PARTITION BY (toDate(create_date), series_id) ORDER BY (goods_id, item_name) SETTINGS index_granularity = 8192;

-- 源数据表2
CREATE TABLE business.order_list(
    order_id          Int64,
    client_id         Int64,
    goods_id          Int64,
    shop_id           UInt64,
    order_date        DateTime
) ENGINE = CnchMergeTree PARTITION BY (toDate(order_date), shop_id) ORDER BY (order_id,goods_id, client_id) SETTINGS index_granularity = 8192;

-- 目标聚合表
CREATE TABLE business.order_statistics (date Date, encoded_shop_id UInt64, encoded_goods_series_id UInt64, item_id Int64, total_price SimpleAggregateFunction(sum, Float64), max_price SimpleAggregateFunction(max, Float64)) ENGINE =     CnchAggregatingMergeTree() PARTITION BY (date, toUInt64(encoded_shop_id + 10)) ORDER BY (date, encoded_shop_id, encoded_goods_series_id, item_id) SETTINGS index_granularity = 8192;

-- 异步物化视图
CREATE MATERIALIZED VIEW business.order_report_mv TO business.order_statistics
REFRESH ASYNC START('2023-12-05 10:00:00') EVERY(INTERVAL 1 MINUTE)
AS SELECT
    date_trunc('month', toDate(order.order_date)) as date,
    multiIf(order.shop_id >= 2702, toUInt64(30000), shop_id <= 2701, toUInt64(40000), toUInt64(50000)) as encoded_shop_id,
    multiIf(good.series_id = 1, toUInt64(100), good.series_id = 2, toUInt64(101), good.series_id = 3, toUInt64(103), toUInt64(10)) as encoded_goods_series_id, 
    order.order_id as item_id,
    sum(good.price) as total_price, 
    max(good.price) as max_price
FROM business.order_list as order INNER JOIN business.goods as good ON good.goods_id = order.goods_id WHERE date > '2023-04-01' and date <= '2023-12-01' and order.shop_id >= 2702 GROUP BY date, encoded_shop_id, encoded_goods_series_id, item_id;