動態物化視圖功能(Delta Live Materialized View),協助使用者構建簡單易用的累加式更新Pipeline。本文介紹MaxCompute動態物化視圖的相關操作。
功能介紹
動態物化視圖相比全量重新整理物化視圖,能夠平衡資料新鮮度和計算代價,充分利用存量的計算結果,通過智能的增量計算演算法,減少計算代價,並提高資料新鮮度。
整體架構

核心優勢
MaxCompute的動態物化視圖Delta Live MV功能具備以下優勢:
聲明式SQL、免營運、自動數倉分層。
簡化數倉架構,一份計算邏輯,一個引擎,同時支援增量計算和全量計算,同時滿足低延遲和高吞吐需求。
成本效益,平衡資料新鮮度和成本,高效處理增全量ETL。
適用情境
動態物化視圖功能適用於以下情境:
離線業務即時化
從T+1數倉演化到分鐘級近即時數倉。
增全量一體
當天分區近即時增量計算:業務資料新鮮度要求高,計算性價比高。
(可選操作)歷史分區回刷:資料歸檔、修正,用於後續大規模資料分析。
全面支援各種SQL邏輯的增量計算,包含以下常見的SQL運算元:
雙流INNER JOIN
雙流(LEFT/RIGHT)OUTER JOIN
任意AGGREGATE(除UDAF外),包括無GROUP BY、無AGG的Function。
WINDOW
TableFunctionScan
UNION ALL
FILTER/Project
SUBQUERY
注意事項
源表(source table)已開啟CDC功能。目前支援的源表類型如下:
Delta Table增量表,並且需要開啟CDC功能。
動態物化視圖表。動態物化視圖預設已開啟CDC功能。
動態物化視圖不能包含非確定性計算,如RAND函數、UDF等。
建立動態物化視圖
文法格式
CREATE MATERIALIZED VIEW [IF NOT EXISTS][<project_name>.]<mv_name>
[LIFECYCLE <days>] --指定生命週期
[BUILD DEFERRED] -- 指定是在建立時只產生表結構,不產生資料
[(<col_name> [COMMENT <col_comment>],...)] --列注釋
[DISABLE REWRITE] --指定是否用於改寫
[COMMENT <table comment>] --表注釋
[PARTITIONED ON/BY (<col_name> [, <col_name>, ...]) --建立物化視圖表為分區表
[REFRESH EVERY <num> MINUTES/HOURS/DAYS] -- 設定物化視圖定時更新間隔
TBLPROPERTIES(
"refresh_mode"="incremental"
[,"enable_auto_refresh"="true"] --指定是否開啟自動重新整理
[,"refresh_cron"="xx"] --根據cron定時器,可以配置定時間隔更新或者定點更新,間隔定點更新等
[,"refresh_job_settings"="xx"]
)
AS <select_statement>;動態物化視圖Delta Live MV的文法相容主要普通物化視圖的文法,目前存在以下差異:
當前不支援將動態物化視圖建立為聚簇表。
動態物化視圖不支援將
enable_auto_substitute參數設定為true。動態物化視圖是非同步物化視圖形態,所使用的base table資料不一定是最新版本,與enable_auto_substitute設定為true時衝突。
參數說明
參數 | 是否必填 | 描述 |
project_name | 否 | 專案名稱。 |
mv_name | 是 | Delta Live MV名稱。 |
LIFECYCLE <days> | 否 | 指定生命週期。 |
BUILD DEFERRED | 否 | 指定在建立時只產生表結構,不產生資料。 |
col_name | 否 | 列名。 |
col_comment | 否 | 列注釋。 |
DISABLE REWRITE | 否 | 指定是否用於改寫。 |
table comment | 否 | 表注釋。 |
REFRESH EVERY <num> MINUTES/HOURS/DAYS | 否 | 指定重新整理的調度間隔,最小值為1分鐘。 |
enable_auto_refresh | 否 | 是否開啟自動重新整理。
|
refresh_mode | 否 | 重新整理模式。
|
refresh_cron | 否 | 指定Cron運算式以設定重新整理頻率,可配置定時間隔更新、定點更新或間隔定點更新等。 取值為QUARTZ Cron格式的字串,使用詳情請參見Cron expression examples。樣本如下: |
refresh_job_settings | 否 |
|
select_statement | 是 | SQL查詢語句。 |
使用樣本
樣本1:建立簡單動態物化視圖
定義一個名為mv1的動態物化視圖,每5分鐘自動進行一次增量重新整理。其中source為一張開啟CDC功能的Delta Table。
CREATE MATERIALIZED VIEW IF NOT EXISTS mv1
REFRESH EVERY 5 MINUTES
TBLPROPERTIES("enable_auto_refresh"="true", "refresh_mode"="incremental")
AS
SELECT name, COUNT(*) FROM source GROUP BY name;樣本2:建立含通用調優參數的動態物化視圖
SET odps.task.major.version=sql_flighting_dlmv;
CREATE MATERIALIZED VIEW IF NOT EXISTS part_dlmv_department
PRIMARY KEY(dept_id) -- 可以通過SQL邏輯推匯出pk列為dept_id(通過base表的pk列推匯出來),
-- 預期不需要顯示聲明,但由於分區mv目前只支援BUILD DEFERRED,
-- 該模式下還沒有做pk推導的功能,所以需要顯示的聲明pk
LIFECYCLE 10
BUILD DEFERRED
PARTITIONED BY (pt)
TBLPROPERTIES('refresh_mode'='incremental',
'refresh_job_settings'='set odps.task.major.version=sql_flighting_dlmv;')
AS
SELECT *, get_setting('odps.custom.setting.department.pt') AS pt FROM t_department; MV 重新整理的主鍵要求:
目前MV重新整理要求 MV 本身是一張PK(主鍵)表。區別於PK Delta Table,MV 由一段SQL邏輯產生。建立 MV 時是否需要顯式聲明 Primary Key,取決於以下情況:
SQL邏輯可自動推匯出PK時
例如,SQL 中包含 GROUP BY key,則 MV 的主鍵自動推導為 key,無需顯式聲明。可通過
DESC EXTENDED mvName;命令查看推匯出的主鍵列。SQL邏輯無法自動推匯出主鍵時
方式一:修改 MV 的 SQL 邏輯,添加 GROUP BY 使其滿足自動推導條件。
方式二:顯式聲明 Primary Key。需要注意,資料本身必須滿足唯一性限制式。 系統會儘力進行資料唯一性校正,即每次增量重新整理時均會執行唯一性檢查,初始化階段目前尚有最佳化空間,後續將儘快補充主鍵唯一性檢查能力。
分區 MV 的特殊要求
分區 MV 當前僅支援 BUILD DEFERRED模式,該模式下暫不支援主鍵自動推導,因此必須顯式聲明 Primary Key。
建立分區DLMV
情境一:使用分區 DLMV 表達當天入倉的增量資料以及歷史的全量資料
SET odps.task.major.version=sql_flighting_dlmv;
CREATE MATERIALIZED VIEW IF NOT EXISTS part_dlmv_department
PRIMARY KEY(dept_id) -- 可以通過SQL邏輯推匯出pk列為dept_id(通過base表的pk列推匯出來),
-- 預期不需要顯示聲明,但由於分區mv目前只支援BUILD DEFERRED,
-- 該模式下還沒有做pk推導的功能,所以需要顯示的聲明pk
LIFECYCLE 10
BUILD DEFERRED
PARTITIONED BY (pt)
TBLPROPERTIES('refresh_mode'='incremental',
'refresh_job_settings'='set odps.task.major.version=sql_flighting_dlmv;')
AS
-- t_department 是近即時入倉表,主要描述使用者當天的增量資料
SELECT *, get_setting('odps.custom.setting.department.pt') AS pt FROM t_department;
UNION ALL
-- history_t_department 是歷史分區表,包含了歷史所有資料
SELECT * FROM history_t_department;情境二:通過group by key推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
CREATE MATERIALIZED VIEW dlmv_pt
PRIMARY KEY(value) -- 可以通過SQL邏輯推匯出pk列為value(gropy by value),
-- 預期不需要顯示聲明pk列,但分區dlmv當前只支援BUILD DEFERRED模式,
-- 該模式下還沒有做pk推導的功能,所以需要顯示的聲明pk列
build deferred
partitioned BY (pt)
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS SELECT *, get_setting('odps.custom.setting.dlmv_pt.pt') AS pt FROM (SELECT value, MAX(value2) FROM dlmv_base_table GROUP BY value) t;情境三:通過base表的pk推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
CREATE MATERIALIZED VIEW dlmv_pt
PRIMARY KEY(key) --可以通過SQL邏輯推匯出pk列為key(通過base表的pk列推匯出來),預期不需要顯示聲明pk列, 但分區dlmv當前只支援BUILD DEFERRED模式,該模式下還沒有做pk推導的功能,所以需要顯示的聲明pk列
build deferred
partitioned BY (pt)
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS
SELECT key, value, value2, get_setting('odps.custom.setting.dlmv_pt.pt') as pt FROM dlmv_base_table;情境四:無法推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
# 1. 直接顯示聲明pk列
CREATE MATERIALIZED VIEW dlmv_pt
primary key(value) -- 通過SQL邏輯推匯出不出來pk列為valu,但使用者側知道資料本身是滿足pk唯一性的, 需要顯示聲明pk列
build deferred
partitioned BY (pt)
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS
SELECT value, value2, get_setting('odps.custom.setting.dlmv_pt.pt') as pt FROM dlmv_base_table;
# 2. 改造SQL邏輯,從而能推匯出pk列
-- 如果使用者側無法保證value列值的唯一性,則可以通過group by邏輯進行改造,如下所示:
CREATE MATERIALIZED VIEW dlmv_pt
primary key(value) -- 可以通過SQL邏輯推匯出pk列為value(gropy by value),預期不需要顯示聲明pk列,但分區dlmv當前只支援BUILD DEFERRED模式,該模式下還沒有做pk推導的功能,所以需要顯示的聲明pk列
build deferred
partitioned BY (pt)
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS SELECT value, MAX(value2), get_setting('odps.custom.setting.dlmv_pt.pt') as pt FROM dlmv_base_table GROUP BY value;建立非分區DLMV
情境一:通過group by key推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
CREATE MATERIALIZED VIEW dlmv
-- primary key(value) 可以通過SQL邏輯推匯出pk列為value(gropy by value),不需要顯示聲明pk列
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS SELECT value, MAX(value2) FROM dlmv_base_table GROUP BY value;情境二:通過base表的pk推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
CREATE MATERIALIZED VIEW dlmv
-- primary key(key) 可以通過SQL邏輯推匯出pk列為key(通過base表的pk列推匯出來),不需要顯示聲明pk列
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS
SELECT key, value, value2 FROM dlmv_base_table;情境三:無法推匯出dlmv的pk列。
// pk delta table
CREATE TABLE dlmv_base_table(
key STRING NOT NULL PRIMARY KEY,
value BIGINT,
value2 BIGINT
)
STORED AS ALIORC
TBLPROPERTIES (
'transactional' = 'true',
'cdc.insert.into.passthrough.enable' = 'true',
'acid.cdc.mode.enable' = 'true',
'acid.cdc.build.async' = 'false'
);
# 1. 顯示聲明pk列
CREATE MATERIALIZED VIEW dlmv
primary key(value) -- 通過SQL邏輯推匯出不出來pk列為valu,但使用者側知道資料本身是滿足pk唯一性的, 需要顯示聲明pk列
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS
SELECT value, value2 FROM dlmv_base_table;
# 2. 改造SQL邏輯,從而能推匯出pk列
-- 如果使用者側無法保證value列值的唯一性,則可以通過group by邏輯進行改造,如下所示:
CREATE MATERIALIZED VIEW dlmv
-- primary key(value) 可以通過SQL邏輯推匯出pk列為value(gropy by value),不需要顯示聲明pk列
TBLPROPERTIES (
'refresh_mode' = 'incremental',
'enable_auto_refresh' = 'true'
)
AS SELECT value, MAX(value2) FROM dlmv_base_table GROUP BY value;樣本3:建立單分區增量重新整理的動態物化視圖
建立分區動態物化視圖時,需添加BUILD DEFERRED關鍵字,表示僅執行DDL操作。
-- 建立動態物化視圖
CREATE MATERIALIZED VIEW dlmv_pt
PRIMARY KEY(value) BUILD DEFERRED PARTITIONED BY (ds) TBLPROPERTIES
('refresh_mode'='incremental', 'enable_auto_refresh'='true')
AS SELECT value, AVG(value2), ds FROM dlmv_pt_src GROUP BY value, ds;
-- 重新整理單分區
ALTER MATERIALIZED VIEW dlmv_pt REBUILD PARTITION(ds='20250730');重新整理動態物化視圖的操作詳情,請參見手動重新整理。
樣本4:建立包含參數化定義的動態物化視圖
支援參數化定義,可將離線分區作業遷移到增量作業。
支援get_setting函數,用於擷取Session Flag中設定的參數值。需要以
dps.custom.setting為首碼。傳統離線作業中的
${biz_date}替換為get_setting(odps.custom.setting.xx),完成參數化改造。動態物化視圖重新整理語句前添加Session Flag
set odps.custom.setting.xx=yy。實際運行時,動態物化視圖中的
get_setting(odps.custom.setting.xx)會被MaxCompute最佳化器自動替換為yy。
樣本如下:
-- 建立動態物化視圖
CREATE MATERIALIZED VIEW mv1
BUILD DEFERRED -- 只做ddl,不產生資料
PARTITIONED BY (ds)
REFRESH EVERY 5 minutes
TBLPROPERTIES("enable_auto_refresh"="true", "refresh_mode"="incremental")
AS
SELECT A.* FROM A JOIN B ON A.c1 = B.c1
AND A.ds=get_setting('odps.custom.setting.bizdate.a')
AND B.ds=get_setting('odps.custom.setting.bizdate.b');
-- 重新整理邏輯,通過Dataworks調度,自動替換${biz_date}和${yesterday}
SET odps.custom.setting.bizdate.a=${biz_date};
SET odps.custom.setting.bizdate.b=${yesterday};
ALTER MATERIALIZED VIEW mv1 REBUILD PARTITION(ds=${biz_date});管理動態物化視圖
刪除
DROP MATERIALIZED VIEW [IF EXISTS] [<project_name>.]<mv_name>;手動重新整理
動態物化視圖提供手動重新整理能力,僅支援重新整理單分區。其文法和普通物化視圖相同:
ALTER MATERIALIZED VIEW [<project_name>.]<mv_name>
REBUILD [PARTITION(<ds>=max_pt(<table_name>),<expression1>...)];其中ds為分區列。
關閉自動重新整理
通過如下命令修改物化視圖的TBLPROPERTIES參數,以關閉自動重新整理功能。
ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="false");恢複自動重新整理
通過如下命令修改物化視圖的TBLPROPERTIES參數,以開啟或者恢複自動重新整理。
ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="true");修改重新整理頻率
通過如下命令修改動態物化視圖的重新整理頻率。
ALTER MATERIALIZED VIEW <mv_name>
SET TBLPROPERTIES("refresh_interval_minutes"="xx");refresh_interval_minutes參數最小取值為1,建議該值小於base table的CDC生命週期。
查看動態物化視圖
查看資料變更歷史
通過如下命令查看動態物化視圖資料的變更記錄。
SHOW HISTORY FOR TABLE <mv_name>;結果樣本:
ObjectType ObjectId ObjectName VERSION(LSN) Time Operation
TABLE d95ec7015e8b432e8e0092d01da962a9 incremental_mv 0000000000000001 2024-08-18 21:06:32 CREATE
TABLE d95ec7015e8b432e8e0092d01da962a9 incremental_mv 0000000000000002 2024-08-18 21:11:13 UPDATE查看重新整理記錄
通過如下命令查看動態物化視圖的重新整理記錄(僅針對Refresh操作)。
SELECT * FROM
Delta_Live_MV_Refresh_History(['<project_name>', '<schema_name>',]'<table_name>');參數說明
參數 | 描述 |
project_name | 專案名稱。 |
schema_name | Schema名稱。 |
table_name | 表名稱。 |
傳回值說明
欄位名稱 | 描述 |
project_name | Delta Live MV所屬的Project。 |
schema_name | Delta Live MV所屬的Schema。 |
name | Delta Live MV名稱。 |
refresh_start_time | 重新整理開始時間。 |
refresh_end_time | 重新整理結束時間。任務狀態為RUNNING時,該值為NULL。 |
instance_id | 作業ID,通過ID可擷取Logview。 |
duration_in_seconds | 重新整理耗時。 |
state | 作業狀態。
|
refresh_trigger | 重新整理方式。
|
refresh_mode | 重新整理模式。
|
error_message | 重新整理失敗的資訊。若重新整理成功,則該值為NULL。 |
source_tables | 記錄了Delta Live MV使用的基表名稱以及對應的版本。 |
numInsertedRows | INSERT行數。 |
numDeletedRows | DELETE行數。 |
計費規則
動態物化視圖包含計算和儲存兩部分費用。與普通物化視圖操作計算儲存計費方式一致。
計算費用
建立或重新整理動態物化視圖過程中,涉及到實際啟動作業計算的,會消耗計算資源產生計算費用,其計費規則和普通SQL作業一致。
觸發自動重新整理功能時,若無實際增量資料變化,則不會啟動SQL作業進行重新整理操作,不產生費用。
建議將動態物化視圖單獨放在某個Project中,方便跟蹤自動重新整理的作業及其計算資源消耗和費用。
儲存費用
動態物化視圖和普通物化視圖或者普通表一樣,按照正常儲存計量計費。
動態物化視圖對某些operator可能會採取基於state的增量計算演算法,會產生內部state table消耗一定的儲存空間。
動態物化視圖需要增量CDC、Time Travel儲存開銷,這部分儲存開銷和普通Delta Table類似。