A página APPLY CHANGES APIs: Simplificar a captura de dados de alterações (CDC) com Delta Live Tables
Delta Live Tables simplifica a captura de dados de alterações (CDC) (CDC) com APPLY CHANGES
e APPLY CHANGES FROM SNAPSHOT
APIs. A interface que o senhor utiliza depende da origem dos dados de modificação:
Use
APPLY CHANGES
para processar alterações de um feed de dados de alteração (CDF).Use
APPLY CHANGES FROM SNAPSHOT
(Public Preview) para processar alterações no Snapshot do banco de dados.
Anteriormente, a instrução MERGE INTO
era comumente usada para processar registros CDC em Databricks. No entanto, MERGE INTO
pode produzir resultados incorretos devido a registros fora de sequência ou exigir uma lógica complexa para reordenar os registros.
A API APPLY CHANGES
é compatível com as interfaces SQL e Python do Delta Live Tables. A API APPLY CHANGES FROM SNAPSHOT
A API é compatível com a interface Python do Delta Live Tables.
Tanto APPLY CHANGES
quanto APPLY CHANGES FROM SNAPSHOT
suportam a atualização de tabelas usando SCD tipo 1 e tipo 2:
Use o SCD tipo 1 para atualizar os registros diretamente. O histórico não é mantido para registros atualizados.
Use o SCD tipo 2 para manter um histórico de registros, em todas as atualizações ou em atualizações de um conjunto específico de colunas.
Para obter sintaxe e outras referências, consulte:
captura de dados de alterações (CDC) de um feed de alterações com Python em Delta Live Tables
captura de dados de alterações (CDC) com SQL em Delta Live Tables
Controlar o gerenciamento de marca para exclusão para querySCD tipo 1
Observação
Este artigo descreve como atualizar tabelas em seu pipeline Delta Live Tables com base nas alterações nos dados de origem. Para saber como registrar e consultar informações de alteração em nível de linha para tabelas Delta, consulte Usar o feed de dados de alteração do Delta Lake no Databricks.
Requisitos
Para usar o CDC APIs, seu pipeline deve estar configurado para usar serverless o pipeline DLT ou Delta Live Tables Pro
as Advanced
edições ou .
Como o CDC é implementado com a API APPLY CHANGES
?
Ao tratar automaticamente os registros fora de sequência, a API APPLY CHANGES
do Delta Live Tables garante o processamento correto dos registros CDC e elimina a necessidade de desenvolver uma lógica complexa para tratar os registros fora de sequência. É necessário especificar uma coluna nos dados de origem para sequenciar os registros, que o Delta Live Tables interpreta como uma representação monotonicamente crescente da ordenação adequada dos dados de origem. O Delta Live Tables trata automaticamente os dados que chegam fora de ordem. Para alterações SCD tipo 2, o Delta Live Tables propaga os valores de sequenciamento apropriados para as colunas __START_AT
e __END_AT
da tabela de destino. Deve haver uma atualização distinta por key em cada valor de sequenciamento, e não há suporte para valores de sequenciamento NULL.
Para executar o processamento em CDC com APPLY CHANGES
, o senhor primeiro cria uma tabela de transmissão e, em seguida, usa a instrução APPLY CHANGES INTO
em SQL ou a função apply_changes()
em Python para especificar a fonte, a chave e o sequenciamento do feed de modificação. Para criar a tabela de transmissão de destino, use a instrução CREATE OR REFRESH STREAMING TABLE
em SQL ou a função create_streaming_table()
em Python. Veja os exemplos de processamento de SCD tipo 1 e tipo 2.
Para obter detalhes sobre a sintaxe, consulte a referência SQL do Delta Live Tables ou a referência Python.
Como o CDC é implementado com a API APPLY CHANGES FROM SNAPSHOT
?
Visualização
A API APPLY CHANGES FROM SNAPSHOT
está em pré-visualização pública.
APPLY CHANGES FROM SNAPSHOT
é um API declarativo que determina com eficiência as alterações nos dados de origem comparando uma série de Snapshot em ordem e, em seguida, executa o processamento necessário para CDC o processamento dos registros no Snapshot. APPLY CHANGES FROM SNAPSHOT
é compatível apenas com a interface Python do Delta Live Tables.
APPLY CHANGES FROM SNAPSHOT
suporta a ingestão de Snapshot de vários tipos de fontes:
Use a ingestão periódica Snapshot para ingerir o Snapshot de uma tabela existente ou view.
APPLY CHANGES FROM SNAPSHOT
tem uma interface simples e otimizada para suportar a ingestão periódica de Snapshot a partir de um objeto de banco de dados existente. Um novo Snapshot é ingerido a cada atualização do pipeline, e o tempo de ingestão é usado como a versão do Snapshot. Quando um pipeline é executado no modo contínuo, vários instantâneos são ingeridos a cada atualização do pipeline em um período determinado pela configuração do intervalo de acionamento do fluxo que contém o processamento APPLY CHANGES FROM Snapshot.Use a ingestão histórica do Snapshot para processar arquivos que contenham o Snapshot do banco de dados, como o Snapshot gerado a partir de um banco de dados Oracle ou MySQL ou um data warehouse.
Para executar o processamento de CDC a partir de qualquer tipo de fonte com APPLY CHANGES FROM SNAPSHOT
, o senhor primeiro cria uma tabela de transmissão e, em seguida, usa a função apply_changes_from_snapshot()
em Python para especificar a Snapshot, a chave e outros argumentos necessários para implementar o processamento. Veja os exemplos de ingestão periódica em Snapshot e ingestão histórica em Snapshot .
O Snapshot passado para API deve estar em ordem crescente por versão. Se o site Delta Live Tables detectar um Snapshot fora de ordem, será lançado um erro.
Para obter detalhes sobre a sintaxe, consulte a referência do Delta Live Tables Python.
Limitações
O destino de uma consulta APPLY CHANGES
ou APPLY CHANGES FROM SNAPSHOT
não pode ser usado como fonte para uma tabela de transmissão. Uma tabela que lê a partir do destino de uma consulta APPLY CHANGES
ou APPLY CHANGES FROM SNAPSHOT
deve ser uma tabela materializada view.
Exemplo: Processamento de SCD tipo 1 e SCD tipo 2 com dados de origem CDF
As seções a seguir fornecem exemplos de consultas Delta Live Tables SCD tipo 1 e tipo 2 que atualizam tabelas de destino com base em eventos de origem de um feed de dados de alteração:
Cria novos registros de usuário.
Exclui um registro de usuário.
Atualiza os registros de usuários. No exemplo do SCD tipo 1, as últimas
UPDATE
operações chegam atrasadas e são descartadas da tabela de destino, demonstrando o tratamento de eventos fora de ordem.
Os exemplos a seguir pressupõem familiaridade com a configuração e atualização de pipelines do Delta Live Tables. Consulte Tutorial: Execute seu primeiro pipeline das Delta Live Tables.
Para executar esses exemplos, você deve começar criando um dataset de amostra. Consulte Gerar dados de teste.
A seguir encontram-se registros de entrada para esses exemplos:
userId |
name |
city |
operation |
sequenceNum |
---|---|---|---|---|
124 |
Raul |
Oaxaca |
INSERT |
1 |
123 |
Isabel |
Monterrey |
INSERT |
1 |
125 |
Mercedes |
Tijuana |
INSERT |
2 |
126 |
Lily |
Cancun |
INSERT |
2 |
123 |
null |
null |
DELETE |
6 |
125 |
Mercedes |
Guadalajara |
UPDATE |
6 |
125 |
Mercedes |
Mexicali |
UPDATE |
5 |
123 |
Isabel |
Chihuahua |
UPDATE |
5 |
Se você cancelar o comentário da linha final nos dados de exemplo, ele inserirá o seguinte registro que especifica onde os registros devem ser truncados:
userId |
name |
city |
operation |
sequenceNum |
---|---|---|---|---|
null |
null |
null |
TRUNCATE |
3 |
Observação
Todos os exemplos a seguir incluem opções para especificar operações DELETE
e TRUNCATE
, mas cada uma delas é opcional.
Processar atualizações do SCD tipo 1
O exemplo a seguir demonstra o processamento de atualizações SCD tipo 1:
import dlt
from pyspark.sql.functions import col, expr
@dlt.view
def users():
return spark.readStream.table("cdc_data.users")
dlt.create_streaming_table("target")
dlt.apply_changes(
target = "target",
source = "users",
keys = ["userId"],
sequence_by = col("sequenceNum"),
apply_as_deletes = expr("operation = 'DELETE'"),
apply_as_truncates = expr("operation = 'TRUNCATE'"),
except_column_list = ["operation", "sequenceNum"],
stored_as_scd_type = 1
)
-- Create and populate the target table.
CREATE OR REFRESH STREAMING TABLE target;
APPLY CHANGES INTO
live.target
FROM
stream(cdc_data.users)
KEYS
(userId)
APPLY AS DELETE WHEN
operation = "DELETE"
APPLY AS TRUNCATE WHEN
operation = "TRUNCATE"
SEQUENCE BY
sequenceNum
COLUMNS * EXCEPT
(operation, sequenceNum)
STORED AS
SCD TYPE 1;
Após executar o exemplo do SCD tipo 1, a tabela de destino contém os seguintes registros:
userId |
name |
city |
---|---|---|
124 |
Raul |
Oaxaca |
125 |
Mercedes |
Guadalajara |
126 |
Lily |
Cancun |
Depois de executar o exemplo do SCD tipo 1 com o registro TRUNCATE
adicional, os registros 124
e 126
são truncados devido à operação TRUNCATE
em sequenceNum=3
, e a tabela de destino contém o seguinte registro:
userId |
name |
city |
---|---|---|
125 |
Mercedes |
Guadalajara |
Processar atualizações do SCD tipo 2
O exemplo a seguir demonstra o processamento de atualizações SCD tipo 2:
import dlt
from pyspark.sql.functions import col, expr
@dlt.view
def users():
return spark.readStream.table("cdc_data.users")
dlt.create_streaming_table("target")
dlt.apply_changes(
target = "target",
source = "users",
keys = ["userId"],
sequence_by = col("sequenceNum"),
apply_as_deletes = expr("operation = 'DELETE'"),
except_column_list = ["operation", "sequenceNum"],
stored_as_scd_type = "2"
)
-- Create and populate the target table.
CREATE OR REFRESH STREAMING TABLE target;
APPLY CHANGES INTO
live.target
FROM
stream(cdc_data.users)
KEYS
(userId)
APPLY AS DELETE WHEN
operation = "DELETE"
SEQUENCE BY
sequenceNum
COLUMNS * EXCEPT
(operation, sequenceNum)
STORED AS
SCD TYPE 2;
Após executar o exemplo do SCD tipo 2, a tabela de destino contém os seguintes registros:
userId |
name |
city |
__START_AT |
__END_AT |
---|---|---|---|---|
123 |
Isabel |
Monterrey |
1 |
5 |
123 |
Isabel |
Chihuahua |
5 |
6 |
124 |
Raul |
Oaxaca |
1 |
null |
125 |
Mercedes |
Tijuana |
2 |
5 |
125 |
Mercedes |
Mexicali |
5 |
6 |
125 |
Mercedes |
Guadalajara |
6 |
null |
126 |
Lily |
Cancun |
2 |
null |
Uma query SCD tipo 2 também pode especificar um subconjunto de colunas de saída a serem rastreadas para história na tabela de destino. As alterações em outras colunas são atualizadas no local, em vez de gerar novos registros de história. O exemplo a seguir demonstra a exclusão da coluna city
do acompanhamento:
O exemplo a seguir demonstra o uso do histórico de rastreamento com o SCD tipo 2:
import dlt
from pyspark.sql.functions import col, expr
@dlt.view
def users():
return spark.readStream.table("cdc_data.users")
dlt.create_streaming_table("target")
dlt.apply_changes(
target = "target",
source = "users",
keys = ["userId"],
sequence_by = col("sequenceNum"),
apply_as_deletes = expr("operation = 'DELETE'"),
except_column_list = ["operation", "sequenceNum"],
stored_as_scd_type = "2",
track_history_except_column_list = ["city"]
)
-- Create and populate the target table.
CREATE OR REFRESH STREAMING TABLE target;
APPLY CHANGES INTO
live.target
FROM
stream(cdc_data.users)
KEYS
(userId)
APPLY AS DELETE WHEN
operation = "DELETE"
SEQUENCE BY
sequenceNum
COLUMNS * EXCEPT
(operation, sequenceNum)
STORED AS
SCD TYPE 2
TRACK HISTORY ON * EXCEPT
(city)
Depois de executar este exemplo sem o registro TRUNCATE
adicional, a tabela de destino conterá os seguintes registros:
userId |
name |
city |
__START_AT |
__END_AT |
---|---|---|---|---|
123 |
Isabel |
Chihuahua |
1 |
6 |
124 |
Raul |
Oaxaca |
1 |
null |
125 |
Mercedes |
Guadalajara |
2 |
null |
126 |
Lily |
Cancun |
2 |
null |
Gerar dados de teste
O código abaixo é fornecido para gerar um exemplo dataset para uso nas consultas de exemplo presentes neste tutorial. Supondo que o senhor tenha as credenciais adequadas para criar um novo esquema e uma nova tabela, é possível executar essas instruções com Notebook ou Databricks SQL. O código a seguir não se destina a ser executado como parte de um Delta Live Tables pipeline:
CREATE SCHEMA IF NOT EXISTS cdc_data;
CREATE TABLE
cdc_data.users
AS SELECT
col1 AS userId,
col2 AS name,
col3 AS city,
col4 AS operation,
col5 AS sequenceNum
FROM (
VALUES
-- Initial load.
(124, "Raul", "Oaxaca", "INSERT", 1),
(123, "Isabel", "Monterrey", "INSERT", 1),
-- New users.
(125, "Mercedes", "Tijuana", "INSERT", 2),
(126, "Lily", "Cancun", "INSERT", 2),
-- Isabel is removed from the system and Mercedes moved to Guadalajara.
(123, null, null, "DELETE", 6),
(125, "Mercedes", "Guadalajara", "UPDATE", 6),
-- This batch of updates arrived out of order. The above batch at sequenceNum 5 will be the final state.
(125, "Mercedes", "Mexicali", "UPDATE", 5),
(123, "Isabel", "Chihuahua", "UPDATE", 5)
-- Uncomment to test TRUNCATE.
-- ,(null, null, null, "TRUNCATE", 3)
);
Exemplo: Periódico Snapshot processing
O exemplo a seguir demonstra o processamento SCD tipo 2 que ingere o Snapshot de uma tabela armazenada em mycatalog.myschema.mytable
. Os resultados do processamento são gravados em uma tabela chamada target
.
mycatalog.myschema.mytable
registros no registro de data e hora 2024-01-01 00:00:00
Chave |
Valor |
---|---|
1 |
a1 |
2 |
a2 |
mycatalog.myschema.mytable
registros no registro de data e hora 2024-01-01 12:00:00
Chave |
Valor |
---|---|
2 |
b2 |
3 |
a3 |
import dlt
@dlt.view(name="source")
def source():
return spark.read.table("mycatalog.myschema.mytable")
dlt.create_streaming_table("target")
dlt.apply_changes_from_snapshot(
target="target",
source="source",
keys=["key"],
stored_as_scd_type=2
)
Após o processamento do Snapshot, a tabela de destino contém os seguintes registros:
Chave |
Valor |
__START_AT |
__END_AT |
---|---|---|---|
1 |
a1 |
2024-01-01 00:00:00 |
2024-01-01 12:00:00 |
2 |
a2 |
2024-01-01 00:00:00 |
2024-01-01 12:00:00 |
2 |
b2 |
2024-01-01 12:00:00 |
null |
3 |
a3 |
2024-01-01 12:00:00 |
null |
Exemplo: Histórico Snapshot processamento
O exemplo a seguir demonstra o processamento SCD tipo 2 que atualiza uma tabela de destino com base em eventos de origem de dois Snapshot armazenados em um sistema de armazenamento cloud:
Snapshot em timestamp
, armazenado em /<PATH>/filename1.csv
Chave |
TrackingColumn |
NonTrackingColumn |
---|---|---|
1 |
a1 |
b1 |
2 |
a2 |
b2 |
4 |
a4 |
b4 |
Snapshot em timestamp + 5
, armazenado em /<PATH>/filename2.csv
Chave |
TrackingColumn |
NonTrackingColumn |
---|---|---|
2 |
a2_novo |
b2 |
3 |
a3 |
b3 |
4 |
a4 |
b4_new |
O exemplo de código a seguir demonstra o processamento de atualizações do tipo 2 do SCD com esse Snapshot:
import dlt
def exist(file_name):
# Storage system-dependent function that returns true if file_name exists, false otherwise
# This function returns a tuple, where the first value is a DataFrame containing the snapshot
# records to process, and the second value is the snapshot version representing the logical
# order of the snapshot.
# Returns None if no snapshot exists.
def next_snapshot_and_version(latest_snapshot_version):
latest_snapshot_version = latest_snapshot_version or 0
next_version = latest_snapshot_version + 1
file_name = "dir_path/filename_" + next_version + ".csv"
if (exist(file_name)):
return (spark.read.load(file_name), next_version)
else:
# No snapshot available
return None
dlt.create_streaming_live_table("target")
dlt.apply_changes_from_snapshot(
target = "target",
source = next_snapshot_and_version,
keys = ["Key"],
stored_as_scd_type = 2,
track_history_column_list = ["TrackingCol"]
)
Após o processamento do Snapshot, a tabela de destino contém os seguintes registros:
Chave |
TrackingColumn |
NonTrackingColumn |
__START_AT |
__END_AT |
---|---|---|---|---|
1 |
a1 |
b1 |
1 |
2 |
2 |
a2 |
b2 |
1 |
2 |
2 |
a2_novo |
b2 |
2 |
null |
3 |
a3 |
b3 |
2 |
null |
4 |
a4 |
b4_new |
1 |
null |
Adicionar, alterar ou excluir dados em uma tabela de streaming de destino
Se o pipeline publicar tabelas no Unity Catalog, você poderá usar instruções de linguagem de manipulação de dados (DML), incluindo instruções de inserção, atualização, exclusão e merge , para modificar as tabelas de transmissão de destino criadas por instruções APPLY CHANGES INTO
.
Observação
As declarações DML que modificam o esquema de tabela de uma tabela de streaming não são suportadas. Certifique-se de que suas instruções DML não tentem evoluir o esquema da tabela.
As instruções DML que atualizam uma tabela de transmissão podem ser executadas somente em um Unity Catalog cluster compartilhado ou em um SQL warehouse usando Databricks Runtime 13.3 LTS e acima.
Como a transmissão requer fonte de dados somente anexada, se o seu processamento exigir transmissão de uma tabela de transmissão de origem com alterações (por exemplo, por instruções DML), defina o sinalizador skipChangeCommits ao ler a tabela de transmissão de origem. Quando
skipChangeCommits
é definido, as transações que excluem ou modificam registros na tabela de origem são ignoradas. Caso o seu processamento não necessite de uma tabela de transmissão, você pode utilizar uma view materializada (que não possui a restrição somente de acréscimo) como tabela de destino.
Como o Delta Live Tables usa uma coluna SEQUENCE BY
especificada e propaga os valores de sequenciamento apropriados para as colunas __START_AT
e __END_AT
da tabela de destino (para SCD tipo 2), é necessário garantir que as instruções DML usem valores válidos para essas colunas a fim de manter a ordenação adequada dos registros. Consulte Como o CDC é implementado com a API APPLY CHANGES?
Para obter mais informações sobre o uso de instruções DML com tabelas de transmissão, consulte Adicionar, alterar ou excluir dados em uma tabela de transmissão.
O exemplo seguinte insere um registro ativo com uma sequência inicial de 5:
INSERT INTO my_streaming_table (id, name, __START_AT, __END_AT) VALUES (123, 'John Doe', 5, NULL);
Obtenha dados sobre registros processados por uma consulta Delta Live Tables CDC
Observação
As métricas a seguir são capturadas apenas por consultas APPLY CHANGES
, e não por consultas APPLY CHANGES FROM SNAPSHOT
.
As seguintes métricas são capturadas pela query APPLY CHANGES
:
num_upserted_rows
: o número de linhas de saída inseridas no dataset durante uma atualização.num_deleted_rows
: o número de linhas de saída existentes excluídas do dataset durante uma atualização.
As num_output_rows
métricas, que são geradas para fluxos não CDC, não são capturadas para apply changes
query.
Quais objetos de dados são usados para o processamento do Delta Live Tables CDC?
Observação: as estruturas de dados a seguir se aplicam somente ao processamento APPLY CHANGES
, não ao processamento APPLY CHANGES FROM SNAPSHOT
.
Quando você declara a tabela de destino no Hive metastore, são criadas duas estruturas de dados:
Uma visualização usando o nome atribuído à tabela de destino.
Uma tabela de apoio interna utilizada pelas Delta Live Tables para gerenciar o processamento de CDC. Essa tabela é nomeada aplicando-se o prefixo
__apply_changes_storage_
no nome da tabela de destino.
Por exemplo, se você declarar uma tabela de destino chamada dlt_cdc_target
, verá uma visualização chamada dlt_cdc_target
e uma tabela chamada __apply_changes_storage_dlt_cdc_target
no metastore. A criação de uma view possibilita que as Delta Live Tables filtrem as informações extras (por exemplo, tombstones e versões) necessárias para lidar com dados fora de ordem. Para ver os dados processados, consulte a view de destino. Como o esquema da tabela do __apply_changes_storage_
pode mudar para suportar futuros recursos ou melhorias, você não deve consultar a tabela para uso de produção. Se você adicionar dados manualmente à tabela, os registros serão assumidos antes de outras alterações, pois as colunas da versão estão faltando.
Se um pipeline for publicado no Unity Catalog, as tabelas de apoio internas ficarão inacessíveis aos usuários.