O MaxCompute introduziu o recurso Delta Live Materialized View (Delta Live MV) para facilitar a criação de pipelines de atualização incremental simples e fáceis de usar. Este tópico descreve as operações da Delta Live MV no MaxCompute.
Introdução
Em comparação com uma materialized view que utiliza atualização completa, a Delta Live Materialized View equilibra a atualidade dos dados e o custo de computação. Ela aproveita integralmente os resultados de computação existentes e usa um algoritmo inteligente de computação incremental para reduzir custos e melhorar a disponibilidade dos dados.
Arquitetura

Principais benefícios
O recurso Delta Live MV no MaxCompute oferece os seguintes benefícios:
SQL declarativo, sem necessidade de manutenção e camadas de data warehouse automatizadas.
Arquitetura de data warehouse simplificada. Uma única lógica e motor de computação suportam tanto a computação incremental quanto a completa, proporcionando baixa latência e alto throughput.
Custo-benefício. Equilibra a atualidade dos dados e os custos, além de processar eficientemente ETL unificado (incremental e completo).
Casos de uso
O recurso Delta Live MV é adequado para os seguintes cenários:
-
Processamento quase em tempo real para cargas de trabalho offline
Evolua um data warehouse T+1 para um data warehouse quase em tempo real com latência de minutos.
-
Processamento unificado incremental e completo
Computação incremental quase em tempo real na partição do dia atual: ideal para cenários que exigem alta atualidade dos dados e computação econômica.
(Opcional) Preenchimento retroativo de partições históricas: arquivamento ou correção de dados para análise em larga escala.
-
Suporte abrangente à computação incremental com vários tipos de lógica SQL, incluindo os seguintes operadores SQL comuns:
INNER JOIN de dois fluxos
OUTER JOIN (LEFT/RIGHT) de dois fluxos
Qualquer função AGGREGATE (exceto funções de agregação definidas pelo usuário - UDAFs), incluindo funções sem cláusula GROUP BY.
WINDOW
TableFunctionScan
UNION ALL
FILTER/Project
SUBQUERY
Pré-requisitos
Você já criou um projeto MaxCompute.
-
O Change Data Capture (CDC) está ativado na tabela de origem. Os seguintes tipos de tabela de origem são compatíveis:
Uma Delta Table com o recurso CDC ativado.
Outra Delta Live MV. O CDC é ativado por padrão para uma Delta Live MV.
Uma Delta Live MV não pode usar computação não determinística, como a função RAND ou funções definidas pelo usuário (UDFs).
Criar uma Delta Live MV
Sintaxe
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>;
A sintaxe de uma Delta Live MV é majoritariamente compatível com a de uma materialized view padrão, com as seguintes diferenças principais:
Não é possível criar uma Delta Live MV como uma tabela clusterizada.
Não é possível definir o parâmetro
enable_auto_substitutecomo true para uma Delta Live MV. Como a Delta Live MV é um tipo de materialized view assíncrona, os dados da tabela base podem não estar na versão mais recente. Isso entra em conflito com o comportamento esperado quandoenable_auto_substituteestá definido como true.
Parâmetros
Parâmetro | Obrigatório | Descrição |
project_name | Não | Nome do projeto. |
mv_name | Sim | Nome da Delta Live MV. |
LIFECYCLE <days> | Não | Especifica o ciclo de vida dos dados. |
BUILD DEFERRED | Não | Indica que apenas o esquema da tabela será criado, sem preenchimento de dados no momento da criação. |
col_name | Não | Nome da coluna. |
col_comment | Não | Comentário da coluna. |
DISABLE REWRITE | Não | Impede o uso da view para reescrita de consultas. |
table comment | Não | Comentário da tabela. |
REFRESH EVERY <num> MINUTES/HOURS/DAYS | Não | Define o intervalo de atualização agendada. O valor mínimo é 1 minuto. |
enable_auto_refresh | Não | Define se a atualização automática deve ser ativada.
|
refresh_mode | Não | Modo de atualização.
|
refresh_cron | Não | Especifica uma expressão Cron para definir a frequência de atualização. Permite configurar agendamentos baseados em intervalo, horário fixo ou mistos. O valor é uma string no formato QUARTZ Cron. Para mais informações, consulte Exemplos de expressões Cron. Exemplo: |
refresh_job_settings | Não |
|
select_statement | Sim | Consulta SQL. |
Exemplos
Exemplo 1: Criar uma Delta Live MV simples
Define uma Delta Live MV chamada mv1 que executa uma atualização incremental automaticamente a cada 5 minutos. A tabela de origem é uma Delta Table com CDC ativado.
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;
Exemplo 2: Criar uma Delta Live MV ajustada
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;
Requisitos de chave primária para atualização de MV
Atualmente, a atualização de uma materialized view exige que a MV possua uma chave primária (PK). Diferentemente de uma Delta Table com PK, uma MV é gerada a partir de lógica SQL. A necessidade de declarar explicitamente uma chave primária ao criar uma MV depende das seguintes situações:
-
Quando a lógica SQL permite inferir a chave primária
Por exemplo, se uma instrução SQL contiver GROUP BY key, a chave primária da MV será automaticamente inferida como key, sem necessidade de declaração explícita. Execute o comando
DESC EXTENDED mvName;para visualizar a coluna de chave primária inferida. -
Quando a lógica SQL não permite inferir a chave primária
Método 1: Modifique a lógica SQL da MV adicionando uma cláusula
GROUP BYpara permitir a inferência automática.Método 2: Declare explicitamente a chave primária. Observe que os dados devem satisfazer a restrição de unicidade. O sistema realiza uma verificação de melhor esforço para unicidade de dados durante cada atualização incremental. O suporte para verificações de unicidade de chave primária durante a fase inicial de construção será aprimorado em uma versão futura.
-
Requisitos especiais para MVs particionadas
Atualmente, MVs particionadas suportam apenas o modo
BUILD DEFERRED. Nesse modo, não há suporte à inferência automática de chave primária. Portanto, declare a chave primária explicitamente.
Delta Live MV Particionada
Cenário 1: Usar uma Delta Live MV particionada para representar dados incrementais do dia atual e dados históricos completos
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;
Cenário 2: Inferir a chave primária da Delta Live MV usando group 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;
Cenário 3: Inferir a chave primária da Delta Live MV a partir da chave primária da tabela base
-- 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;
Cenário 4: A chave primária da Delta Live MV não pode ser inferida
-- 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;
Delta Live MV Não Particionada
Cenário 1: Inferir a chave primária da Delta Live MV usando group 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;
Cenário 2: Inferir a chave primária da Delta Live MV a partir da chave primária da tabela base
-- 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;
Cenário 3: A chave primária da Delta Live MV não pode ser inferida
-- 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;
Exemplo 3: Atualizar uma única partição da MV
Ao criar uma Delta Live MV particionada, inclua a palavra-chave BUILD DEFERRED, que executa apenas a operação DDL.
-- 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');
Para mais informações sobre como atualizar uma Delta Live MV, consulte Atualização manual.
Exemplo 4: Criar uma Delta Live MV parametrizada
Definições parametrizadas permitem migrar jobs de partição offline para jobs incrementais.
A função
get_settingrecupera valores de parâmetros definidos em Session Flags. O nome do parâmetro deve ter o prefixoodps.custom.setting.Em jobs offline tradicionais, substitua variáveis como
${biz_date}porget_setting(odps.custom.setting.xx)para parametrizar a definição.Adicione a Session Flag
set odps.custom.setting.xx=yyantes da instrução de atualização da Delta Live MV.Durante a execução, o otimizador do MaxCompute substitui automaticamente
get_setting(odps.custom.setting.xx)na Delta Live MV poryy.
Veja um exemplo abaixo:
-- 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});
Gerenciar uma Delta Live MV
Excluir uma Delta Live MV
DROP MATERIALIZED VIEW [IF EXISTS] [<project_name>.]<mv_name>;
Atualização manual
É possível atualizar manualmente uma Delta Live MV. Apenas atualizações de partição única são suportadas. A sintaxe é a mesma de uma materialized view padrão:
ALTER MATERIALIZED VIEW [<project_name>.]<mv_name>
REBUILD [PARTITION(<ds>=max_pt(<table_name>),<expression1>...)];
Nesta sintaxe, ds representa a coluna de partição.
Desativar atualização automática
Execute o comando a seguir para modificar as TBLPROPERTIES da materialized view e desativar o recurso de atualização automática:
ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="false");
Retomar atualização automática
Execute o comando a seguir para modificar as TBLPROPERTIES da materialized view e ativar ou retomar a atualização automática:
ALTER MATERIALIZED VIEW <mv_name> SET TBLPROPERTIES("enable_auto_refresh"="true");
Alterar a frequência de atualização
Execute o comando a seguir para alterar a frequência de atualização de uma Delta Live MV:
ALTER MATERIALIZED VIEW <mv_name>
SET TBLPROPERTIES("refresh_interval_minutes"="xx");
O valor mínimo para o parâmetro refresh_interval_minutes é 1. Recomendamos definir este valor como menor que o ciclo de vida do CDC da tabela base.
Visualizar uma Delta Live MV
Visualizar histórico de alterações de dados
Execute o comando a seguir para visualizar o histórico de alterações de dados de uma Delta Live MV:
SHOW HISTORY FOR TABLE <mv_name>;
Resultado de exemplo:
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
Visualizar histórico de atualizações
Execute o comando a seguir para visualizar o histórico de atualizações de uma Delta Live MV.
SELECT * FROM
Delta_Live_MV_Refresh_History(['<project_name>', '<schema_name>',]'<table_name>');
Parâmetros
|
Parâmetro |
Descrição |
|
project_name |
Nome do projeto. |
|
schema_name |
Nome do esquema. |
|
table_name |
Nome da tabela. |
Valores de retorno
Parâmetro | Descrição |
project_name | Projeto que contém a Delta Live MV. |
schema_name | Esquema que contém a Delta Live MV. |
name | Nome da Delta Live MV. |
refresh_start_time | Horário de início da atualização. |
refresh_end_time | Horário de término da atualização. Se o estado do job for RUNNING, o valor deste campo será NULL. |
instance_id | ID do job. Use este ID para obter o Logview. |
duration_in_seconds | Duração da atualização, em segundos. |
state | Estado do job.
|
refresh_trigger | Método que acionou a atualização.
|
refresh_mode | Modo de atualização.
|
error_message | Mensagem de erro caso a atualização tenha falhado. Se a atualização for bem-sucedida, este campo será NULL. |
source_tables | Nomes das tabelas base usadas pela Delta Live MV e suas versões correspondentes. |
numInsertedRows | Número de linhas inseridas. |
numDeletedRows | Número de linhas excluídas. |
Faturamento
Uma Delta Live MV gera taxas de computação e armazenamento. O método de faturamento é o mesmo das operações de materialized view padrão.
-
Taxas de computação
Criar ou atualizar uma Delta Live MV pode iniciar jobs de computação. Esses jobs consomem recursos computacionais e geram taxas de computação. As regras de faturamento seguem o padrão de jobs SQL convencionais.
Se o recurso de atualização automática não detectar alterações nos dados, nenhum job de atualização será iniciado e nenhuma taxa será cobrada.
Colocar Delta Live MVs em um projeto dedicado facilita o rastreamento de jobs de atualização automática, bem como seu consumo de recursos e custos associados.
-
Taxas de armazenamento
O armazenamento de uma Delta Live MV é faturado da mesma forma que uma materialized view padrão ou uma tabela comum.
Para certos operadores, uma Delta Live MV pode usar um algoritmo de computação incremental baseado em estado, o que gera tabelas de estado internas que consomem espaço de armazenamento adicional.
Uma Delta Live MV requer sobrecarga de armazenamento para CDC incremental e Time Travel. Essa sobrecarga é semelhante à de uma Delta Table padrão.