All Products
Search
Document Center

:Delta Live Materialized View (Delta Live MV) (Invitational Preview)

Last Updated:May 06, 2026

MaxCompute introduces the Delta Live Materialized View (Delta Live MV) feature to help you build simple, easy-to-use incremental update pipelines. This topic describes Delta Live MV operations in MaxCompute.

Introduction

Compared to a materialized view that uses a full refresh, a Delta Live Materialized View balances data freshness and compute cost. It fully leverages existing computation results and uses an intelligent incremental computation algorithm to reduce compute cost and improve data freshness.

This feature is currently in Invitational Preview. For usage details, see Usage instructions.

Architecture

image

Key benefits

The Delta Live MV feature in MaxCompute provides the following benefits:

  • Declarative SQL, maintenance-free, and automated data warehouse layering.

  • Simplified data warehouse architecture. A single computation logic and engine supports both incremental and full computation, providing both low latency and high throughput.

  • Cost-effective. It balances data freshness and cost, and efficiently handles unified incremental and full ETL processing.

Use cases

The Delta Live MV feature is suitable for the following scenarios:

  • Near-real-time processing for offline workloads

    Evolve a T+1 data warehouse to a near-real-time data warehouse with minute-level latency.

  • Unified incremental and full processing

    • Near-real-time incremental computation on the current day's partition: Ideal for scenarios that require high data freshness and cost-effective computation.

    • (Optional) Backfill historical partitions: Archive or correct data for large-scale data analysis.

  • Comprehensive support for incremental computation with various types of SQL logic, including the following common SQL operators:

    • Two-stream INNER JOIN

    • Two-stream (LEFT/RIGHT) OUTER JOIN

    • Any AGGREGATE function (except for user-defined aggregate functions (UDAFs)), including functions without a GROUP BY clause.

    • WINDOW

    • TableFunctionScan

    • UNION ALL

    • FILTER/Project

    • SUBQUERY

Prerequisites

  • You have created a MaxCompute project.

  • Change Data Capture (CDC) is enabled on the source table. The following source table types are supported:

    • A Delta Table with the CDC feature enabled.

    • Another Delta Live MV. CDC is enabled by default for a Delta Live MV.

  • A Delta Live MV cannot use non-deterministic computation, such as the RAND function or user-defined functions (UDFs).

Create a Delta Live MV

Syntax

CREATE MATERIALIZED VIEW [IF NOT EXISTS][<project_name>.]<mv_name>
[LIFECYCLE <days>]    -- Specifies the lifecycle.
[BUILD DEFERRED]    -- Creates only the table schema without populating data upon creation.
[(<col_name> [COMMENT <col_comment>],...)]    -- Specifies column comments.
[DISABLE REWRITE]    -- Specifies whether the view is used for query rewrite.
[COMMENT <table comment>]    -- Specifies the table comment.
[PARTITIONED ON/BY (<col_name> [, <col_name>, ...])    -- Creates the materialized view as a partitioned table.
[REFRESH EVERY <num> MINUTES/HOURS/DAYS] -- Sets the scheduled refresh interval.
TBLPROPERTIES(
  "refresh_mode"="incremental"
  [,"enable_auto_refresh"="true"]    -- Specifies whether to enable auto-refresh.
  [,"refresh_cron"="xx"]             -- Uses a cron expression to configure interval-based, fixed-time, or mixed refresh schedules.
  [,"refresh_job_settings"="xx"]
              )
AS <select_statement>;

The syntax for a Delta Live MV is mostly compatible with that of a standard materialized view, with the following key differences:

  • You cannot create a Delta Live MV as a clustered table.

  • You cannot set the enable_auto_substitute parameter to true for a Delta Live MV. A Delta Live MV is a type of asynchronous materialized view, so the data from the base table might not be the latest version. This conflicts with the behavior expected when enable_auto_substitute is set to true.

Parameters

Parameter

Required

Description

project_name

No

The name of the project.

mv_name

Yes

The name of the Delta Live MV.

LIFECYCLE <days>

No

Specifies the data lifecycle.

BUILD DEFERRED

No

Specifies that only the table schema is created, without populating data upon creation.

col_name

No

The column name.

col_comment

No

The column comment.

DISABLE REWRITE

No

Prevents the view from being used for query rewrite.

table comment

No

The table comment.

REFRESH EVERY <num> MINUTES/HOURS/DAYS

No

Specifies the scheduled refresh interval. The minimum value is 1 minute.

enable_auto_refresh

No

Specifies whether to enable auto-refresh.

  • true: Enables auto-refresh.

  • false: Disables auto-refresh.

refresh_mode

No

The refresh mode.

  • full: full refresh.

  • incremental: incremental refresh.

refresh_cron

No

Specifies a Cron expression to set the refresh frequency. You can configure interval-based, fixed-time, or mixed refresh schedules.

The value is a string in QUARTZ Cron format. For more information, see Cron expression examples. Example:

TBLPROPERTIES(
  "enable_auto_refresh"="true",
  "refresh_cron"="xx"
)

refresh_job_settings

No

  • Sets general tuning parameters that are automatically applied during a refresh. Example:

    'refresh_job_settings'='set odps.sql.split.size=128;set odps.sql.reshuffle.dynamicpt
    =false;'
  • The flags set with this parameter have a higher priority than the flags in the current session.

select_statement

Yes

The SQL query.

Examples

Example 1: Create a simple Delta Live MV

Defines a Delta Live MV named mv1 that performs an incremental refresh automatically every 5 minutes. The source table is a Delta Table with CDC enabled.

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;

Example 2: Create a tuned Delta Live MV

SET odps.task.major.version=sql_flighting_dlmv;

CREATE MATERIALIZED VIEW IF NOT EXISTS part_dlmv_department
PRIMARY KEY(dept_id) -- The primary key `dept_id` can be inferred from the SQL logic based on the base table's primary key. 
-- Explicit declaration is typically not required. However, because partitioned MVs currently only support BUILD DEFERRED mode, 
-- which does not support automatic key inference, you must declare the primary key explicitly.
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; 

Primary key requirements for MV refresh

Currently, a materialized view refresh requires the MV to have a primary key (PK). Unlike a PK Delta Table, an MV is generated from SQL logic. Whether you need to explicitly declare a primary key when creating an MV depends on the following situations:

  • When the primary key can be inferred from the SQL logic

    For example, if a SQL statement contains GROUP BY key, the primary key of the MV is automatically inferred to be key and does not need to be explicitly declared. You can run the DESC EXTENDED mvName; command to view the inferred primary key column.

  • When the primary key cannot be inferred from the SQL logic

    • Method 1: Modify the MV's SQL logic by adding a GROUP BY clause to enable automatic inference.

    • Method 2: Explicitly declare the primary key. Note that the data must satisfy the uniqueness constraint. The system performs a best-effort check for data uniqueness during each incremental refresh. Support for primary key uniqueness checks during the initial build phase will be enhanced in a future release.

  • Special requirements for partitioned MVs

    Partitioned MVs currently support only the BUILD DEFERRED mode. In this mode, automatic primary key inference is not supported. Therefore, you must explicitly declare the primary key.

Partitioned Delta Live MV

Scenario 1: Use a partitioned Delta Live MV to represent incremental data for the current day and full historical data

SET odps.task.major.version=sql_flighting_dlmv;

CREATE MATERIALIZED VIEW IF NOT EXISTS part_dlmv_department
PRIMARY KEY(dept_id) -- The primary key `dept_id` can be inferred from the SQL logic based on the base table's primary key.
-- Explicit declaration is typically not required. However, because partitioned MVs currently only support BUILD DEFERRED mode, 
-- which does not support automatic key inference, you must declare the primary key explicitly.
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 is a near-real-time ingestion table that describes the incremental data for the current day.
SELECT *, get_setting('odps.custom.setting.department.pt') AS pt FROM t_department; 
UNION ALL
-- history_t_department is a historical partitioned table that contains all historical data.
SELECT * FROM history_t_department;

Scenario 2: Infer the Delta Live MV's primary key by usinggroup by key

-- 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) -- The primary key `value` can be inferred from the SQL logic (GROUP BY value).
-- Explicit declaration is typically not required. However, because partitioned DLMVs currently support only the BUILD DEFERRED mode,
-- which does not support automatic key inference, you must declare the primary key explicitly.
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;

Scenario 3: Infer the Delta Live MV's primary key from the base table's primary key

-- 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) -- The primary key `key` can be inferred from the SQL logic (derived from the base table's PK).
-- Explicit declaration is typically not required. However, because partitioned DLMVs currently support only the BUILD DEFERRED mode, 
-- which does not support automatic key inference, you must declare the primary key explicitly.
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;

Scenario 4: The Delta Live MV's primary key cannot be inferred

-- 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. Explicitly declare the PK column.
CREATE MATERIALIZED VIEW dlmv_pt
PRIMARY KEY(value) -- The PK cannot be inferred from the SQL logic, but you know the data satisfies PK uniqueness. The PK must be declared explicitly.
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. Modify the SQL logic to allow PK inference.
-- If you cannot guarantee the uniqueness of the 'value' column, modify the logic with a GROUP BY clause, as shown below:
CREATE MATERIALIZED VIEW dlmv_pt
PRIMARY KEY(value) -- The PK `value` can now be inferred from the SQL logic (GROUP BY value).
-- Explicit declaration is typically not required. However, because partitioned DLMVs currently support only the BUILD DEFERRED mode, 
-- which does not support automatic key inference, you must declare the primary key explicitly.
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;

Non-partitioned Delta Live MV

Scenario 1: Infer the Delta Live MV's primary key by usinggroup by key

-- 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) -- The PK `value` can be inferred from the SQL logic (GROUP BY value), so no explicit declaration is needed.
TBLPROPERTIES (
    'refresh_mode'        = 'incremental',
    'enable_auto_refresh' = 'true'
)
AS SELECT value, MAX(value2) FROM dlmv_base_table GROUP BY value;

Scenario 2: Infer the Delta Live MV's primary key from the base table's primary key

-- 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) -- The PK `key` can be inferred from the SQL logic (derived from the base table's PK), so no explicit declaration is needed.
TBLPROPERTIES (
    'refresh_mode'        = 'incremental',
    'enable_auto_refresh' = 'true'
)
AS
SELECT key, value, value2 FROM dlmv_base_table;

Scenario 3: The Delta Live MV's primary key cannot be inferred

-- 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. Explicitly declare the PK column.
CREATE MATERIALIZED VIEW dlmv
PRIMARY KEY(value) -- The PK cannot be inferred from the SQL logic, but you know the data satisfies PK uniqueness. The PK must be declared explicitly.
TBLPROPERTIES (
    'refresh_mode'        = 'incremental',
    'enable_auto_refresh' = 'true'
)
AS
SELECT value, value2 FROM dlmv_base_table;

# 2. Modify the SQL logic to allow PK inference.
-- If you cannot guarantee the uniqueness of the 'value' column, modify the logic with a GROUP BY clause, as shown below:
CREATE MATERIALIZED VIEW dlmv
-- PRIMARY KEY(value) -- The PK `value` can now be inferred from the SQL logic (GROUP BY value), so no explicit declaration is needed.
TBLPROPERTIES (
    'refresh_mode'        = 'incremental',
    'enable_auto_refresh' = 'true'
)
AS SELECT value, MAX(value2) FROM dlmv_base_table GROUP BY value;

Example 3: Refresh a single MV partition

When you create a partitioned Delta Live MV, you must include the BUILD DEFERRED keyword, which performs only the DDL operation.

-- Create the Delta Live MV.
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;

-- Refresh a single partition.
ALTER MATERIALIZED VIEW dlmv_pt REBUILD PARTITION(ds='20250730');
Note

For more information about refreshing a Delta Live MV, see Manual refresh.

Example 4: Create a parameterized Delta Live MV

You can use parameterized definitions to migrate offline partition jobs to incremental jobs.

  • The get_setting function retrieves parameter values set in Session Flags. The parameter name must be prefixed with odps.custom.setting.

  • In traditional offline jobs, replace variables like ${biz_date} with get_setting(odps.custom.setting.xx) to parameterize the definition.

  • Add the Session Flag set odps.custom.setting.xx=yy before the refresh statement for the Delta Live MV.

  • During runtime, the MaxCompute optimizer automatically replaces get_setting(odps.custom.setting.xx) in the Delta Live MV with yy.

The following is an example:

-- Create the Delta Live MV.
CREATE MATERIALIZED VIEW mv1 
BUILD DEFERRED -- Performs only the DDL operation and does not populate data.
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');

-- Refresh logic. DataWorks automatically replaces ${biz_date} and ${yesterday} during scheduling.
SET odps.custom.setting.bizdate.a=${biz_date};
SET odps.custom.setting.bizdate.b=${yesterday};
ALTER MATERIALIZED VIEW mv1 REBUILD PARTITION(ds=${biz_date});

Manage a Delta Live MV

Drop a Delta Live MV

DROP MATERIALIZED VIEW [IF EXISTS] [<project_name>.]<mv_name>;

Manual refresh

You can manually refresh a Delta Live MV. Only single-partition refreshes are supported. The syntax is the same as that for a standard materialized view:

ALTER MATERIALIZED VIEW [<project_name>.]<mv_name>
      REBUILD [PARTITION(<ds>=max_pt(<table_name>),<expression1>...)];

In this syntax, ds is the partition column.

Disable auto-refresh

Run the following command to modify the TBLPROPERTIES of the materialized view to disable the auto-refresh feature:

ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="false");

Resume auto-refresh

Run the following command to modify the TBLPROPERTIES of the materialized view to enable or resume auto-refresh:

ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="true");

Change the refresh frequency

Run the following command to change the refresh frequency of a Delta Live MV:

ALTER MATERIALIZED VIEW <mv_name> 
SET TBLPROPERTIES("refresh_interval_minutes"="xx");
Note

The minimum value for the refresh_interval_minutes parameter is 1. We recommend that you set this value to be shorter than the CDC lifecycle of the base table.

View a Delta Live MV

View data change history

Run the following command to view the data change history of a Delta Live MV:

SHOW HISTORY FOR TABLE <mv_name>;

Sample result:

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

View refresh history

Run the following command to view the refresh history of a Delta Live MV.

SELECT * FROM 
Delta_Live_MV_Refresh_History(['<project_name>', '<schema_name>',]'<table_name>');

Parameters

Parameter

Description

project_name

The name of the project.

schema_name

The name of the schema.

table_name

The name of the table.

Return values

Parameter

Description

project_name

The project that contains the Delta Live MV.

schema_name

The schema that contains the Delta Live MV.

name

The name of the Delta Live MV.

refresh_start_time

The time when the refresh started.

refresh_end_time

The time when the refresh ended. If the job state is RUNNING, the value of this field is NULL.

instance_id

The job ID. You can use this ID to obtain the Logview.

duration_in_seconds

The duration of the refresh, in seconds.

state

The job state.

  • RUNNING: The job is running.

  • TERMINATED: The job completed successfully.

  • FAILED: The job failed.

  • CANCELLED: The job was canceled.

refresh_trigger

The method that triggered the refresh.

  • MANUAL: A user manually triggered the refresh. MaxCompute considers refreshes scheduled by DataWorks as manual triggers.

  • SYSTEM_SCHEDULED: The MaxCompute internal scheduler triggered the refresh.

refresh_mode

The refresh mode.

  • FULL: full refresh.

  • INCREMENTAL: incremental refresh.

  • NO_DATA: No incremental data was available for the refresh.

error_message

The error message if the refresh failed. If the refresh is successful, this field is NULL.

source_tables

The names of the base tables used by the Delta Live MV and their corresponding versions.

numInsertedRows

The number of rows that were inserted.

numDeletedRows

The number of rows that were deleted.

Billing

A Delta Live MV incurs compute and storage fees. The billing method is the same as that for standard materialized view operations.

  • Compute fees

    • Creating or refreshing a Delta Live MV may initiate computation jobs. These jobs consume computing resources and incur compute fees. The billing rules are the same as those for standard SQL jobs.

    • If the auto-refresh feature detects no data changes, it does not initiate a refresh job, and no fees are incurred.

    • Placing Delta Live MVs in a dedicated project makes it easier to track auto-refresh jobs and their resource consumption and fees.

  • Storage fees

    • Storage for a Delta Live MV is billed in the same way as for a standard materialized view or a regular table.

    • For certain operators, a Delta Live MV may use a state-based incremental computation algorithm, which generates internal state tables that consume additional storage space.

    • A Delta Live MV requires storage overhead for incremental CDC and Time Travel. This storage overhead is similar to that of a standard Delta Table.