Pular para o conteúdo principal

Melhores práticas para LakeFlow Pipelines

Aplique estes padrões recomendados ao projetar, criar e operar pipelines, esteja você começando um novo pipeline ou melhorando um existente.

As páginas seguintes abordam com mais detalhes as decisões de design específicas:

tópico

Descrição

Modelagem dimensional em LakeFlow Pipelines

Modele os dados da camada de ouro como fatos e dimensões em um esquema em estrela e mapeie a modelagem dimensional para os tipos de dataset de pipeline.

Garantias de processamento em LakeFlow Pipelines

Entenda a idempotência e onde você obtém exatamente uma vez o processamento por default, versus as bordas em que você precisa adicionar gravações idempotentes.

Organize datasets across LakeFlow Pipelines

Decida quantos conjuntos de dados pertencem a um único pipeline e quando dividir o trabalho em pipelines separados.

Prontidão para produção de LakeFlow Pipelines

Siga uma lista de verificação sobre qualidade, confiabilidade, observabilidade, implementação, custo e governança de dados antes de executar um pipeline sem supervisão.

tópico

Descrição

Modelagem dimensional em LakeFlow Pipelines

Modele os dados da camada de ouro como fatos e dimensões em um esquema em estrela e mapeie a modelagem dimensional para os tipos de dataset de pipeline.

Garantias de processamento em LakeFlow Pipelines

Entenda a idempotência e onde você obtém exatamente uma vez o processamento por default, versus as bordas em que você precisa adicionar gravações idempotentes.

Organize datasets across LakeFlow Pipelines

Decida quantos conjuntos de dados pertencem a um único pipeline e quando dividir o trabalho em pipelines separados.

Prontidão para produção de LakeFlow Pipelines

Siga uma lista de verificação sobre qualidade, confiabilidade, observabilidade, implementação, custo e governança de dados antes de executar um pipeline sem supervisão.

Escolha o tipo de dataset correto

Os pipelines oferecem três tipos de datasets: tabelas de transmissão, views materializadas e views temporárias. Escolher o tipo certo para cada camada do seu pipeline evita custos de compute desnecessários e mantém seu código fácil de entender.

Tabelas de transmissão são a escolha certa para ingestão de dados e transformações de transmissão de baixa latência. Cada linha de entrada é lida e processada apenas uma vez, o que as torna ideais para cargas de trabalho somente de acréscimo, dados de alto volume e processamento orientado a eventos a partir de armazenamento em cloud ou barramentos de mensagens.

As visões materializadas são a escolha certa para transformações complexas e consultas analíticas. Os resultados são pré-computados e mantidos atualizados por meio de incremental refresh, portanto, as consultas a eles são rápidas. Não é possível modificar diretamente os dados em uma view materializada; a definição da query controla a saída.

As visualizações temporárias são visualizações com escopo de pipeline que organizam sua lógica de transformação sem materializar quaisquer dados no armazenamento. Use-as para etapas intermediárias que não precisam de uma tabela própria.

A tabela a seguir resume quando usar cada tipo:

Caso de uso

Tipo recomendado

Motivo

Ingestão a partir de armazenamento em cloud ou barramento de mensagens

Tabela de transmissão

Processa cada registro uma vez; lida com alto volume e cargas de trabalho somente de acréscimo.

Transmissões do CDC (inserções, atualizações, exclusões)

Tabela de transmissão

Usado como destino de AUTO CDC ... INTO para ingestão de CDC ordenada e desduplicada.

Agregações e joins complexos

Visualização materializada

Atualização incremental; evita o recálculo completo a cada atualização.

Aceleração de query de dashboard

Visualização materializada

Resultados pré-computados tornam as consultas mais rápidas do que em tabelas brutas.

Transformações intermediárias (sem leitores downstream)

Vista temporária

Organiza a lógica do pipeline sem incorrer em custos de armazenamento.

Caso de uso

Tipo recomendado

Motivo

Ingestão a partir de armazenamento em cloud ou barramento de mensagens

Tabela de transmissão

Processa cada registro uma vez; lida com alto volume e cargas de trabalho somente de acréscimo.

Transmissões do CDC (inserções, atualizações, exclusões)

Tabela de transmissão

Usado como destino de AUTO CDC ... INTO para ingestão de CDC ordenada e desduplicada.

Agregações e joins complexos

Visualização materializada

Atualização incremental; evita o recálculo completo a cada atualização.

Aceleração de query de dashboard

Visualização materializada

Resultados pré-computados tornam as consultas mais rápidas do que em tabelas brutas.

Transformações intermediárias (sem leitores downstream)

Vista temporária

Organiza a lógica do pipeline sem incorrer em custos de armazenamento.

Para mais informações, consulte Tabelas de streaming, Views materializadas e O que são LakeFlow Pipelines?.

Use CDC declarativo em vez de MERGE imperativo

A implementação da captura de dados de alterações (CDC) com instruções SQL MERGE imperativas requer um código personalizado significativo para lidar corretamente com a ordenação de eventos, desduplicação, atualizações parciais e evolução do esquema. Cada uma dessas preocupações deve ser resolvida de forma independente, e o código resultante é difícil de manter e testar.

Os pipelines fornecem a instrução AUTO CDC ... INTO (SQL) e a função create_auto_cdc_flow() (Python), que lidam com a ordenação, desduplicação, eventos fora de ordem e evolução do esquema de forma declarativa. Você descreve o formato do feed de alterações e da tabela de destino, e o pipeline cuida do resto. AUTO CDC suporta tanto o SCD Tipo 1 (sobrescrita) quanto o SCD Tipo 2 (preservação do histórico).

Para obter mais informações, consulte captura de dados de alterações (CDC) e Snapshots e As APIs AUTO CDC: simplifique a captura de dados de alterações com pipelines.

Garantir a qualidade dos dados com base nas expectativas.

Expectativas são expressões SQL de verdadeiro/falso aplicadas a cada linha que passa por um dataset. Quando uma linha não atende à condição, o pipeline responde de acordo com a política de violação que você configurou. As expectativas emitem métricas para o log de eventos do pipeline, independentemente da política, permitindo acompanhar as tendências de qualidade dos dados ao longo do tempo.

Escolha uma política de violação

Três políticas de violação estão disponíveis. Escolha aquela que corresponde à sua tolerância a dados de baixa qualidade:

  • warn (default): registros que não são válidos são gravados na tabela de destino e sinalizados nas métricas. Use esta política quando precisar capturar todos os dados, mas desejar visibilidade sobre problemas de qualidade.
  • drop : Registros inválidos são descartados antes da gravação. Use esta opção quando linhas com erros forem esperadas e não devem ser propagadas para os fluxos subsequentes.
  • fail : a atualização do pipeline para no primeiro registro inválido. Use isso para dados críticos em que qualquer registro inválido indica um problema upstream sério.

Os exemplos a seguir mostram cada política aplicada a uma tabela de transmissão:

SQL
-- Warn: write invalid records but track them in metrics
CREATE OR REFRESH STREAMING TABLE orders_raw (
CONSTRAINT valid_order_id EXPECT (order_id IS NOT NULL)
) AS SELECT * FROM STREAM read_files("/volumes/raw/orders", format => "json");

-- Drop: discard invalid records before writing
CREATE OR REFRESH STREAMING TABLE orders_clean (
CONSTRAINT non_negative_amount EXPECT (amount >= 0) ON VIOLATION DROP ROW
) AS SELECT * FROM STREAM(orders_raw);

-- Fail: stop the pipeline on any invalid record
CREATE OR REFRESH STREAMING TABLE orders_critical (
CONSTRAINT required_customer_id EXPECT (customer_id IS NOT NULL) ON VIOLATION FAIL UPDATE
) AS SELECT * FROM STREAM(orders_clean);

Colocar registros inválidos em quarentena

Quando você deseja preservar registros perdidos para investigação, em vez de descartá-los silenciosamente, use um padrão de quarentena. Direcione as linhas que não passarem na validação para uma tabela de transmissão separada usando dois fluxos: um que descarta as linhas inválidas da tabela principal e um segundo que grava apenas as linhas inválidas em uma tabela de quarentena. Isso permite investigar, corrigir e reprocessar dados incorretos sem contaminar seu dataset limpo.

Para um exemplo detalhado do padrão de quarentena, consulte Recomendações de expectativa e padrões avançados.

Para obter mais informações sobre expectativas, consulte Gerenciar a qualidade dos dados com expectativas de pipeline.

Parametrize seus pipelines

Os pipelines possuem configurações default de catálogo e esquema, portanto, o código que lê e grava dentro do mesmo catálogo e esquema funciona em diferentes ambientes sem a necessidade de parâmetros. No entanto, se o seu pipeline precisar referenciar um segundo catálogo ou esquema (por exemplo, lendo de um catálogo de origem compartilhado que difere entre desenvolvimento e produção), evite codificar esses nomes diretamente no seu código-fonte. Em vez disso, defina-os como parâmetros de configuração do pipeline (pares key-value definidos nas configurações do pipeline) e faça referência a eles em seu código. Isso permite que uma única base de código seja executada corretamente em diferentes ambientes, trocando os valores dos parâmetros.

SQL
CREATE OR REFRESH MATERIALIZED VIEW transaction_summary AS
SELECT account_id, COUNT(txn_id) AS txn_count, SUM(amount) AS total_amount
FROM ${source_catalog}.sales.transactions
GROUP BY account_id;

Para obter mais informações, consulte Usar parâmetros com pipelines.

Escolha entre o modo de pipeline Trigger e contínuo

Modo Triggered processa todos os dados disponíveis e, em seguida, para. É a escolha certa para a grande maioria dos pipelines: aqueles que são executados em uma programação (por hora, diariamente ou sob demanda) e não exigem frescor de dados inferior a um minuto.

O modo contínuo mantém o cluster em execução e processa novos dados à medida que chegam. É apropriado apenas quando seu caso de uso requer latência na faixa de segundos a minutos. Como o modo contínuo requer um cluster sempre ativo, ele é significativamente mais caro do que o modo Trigger.

O modo em tempo real baseia-se no modo contínuo para atingir latência de sub-segundo, na faixa de milissegundos, para cargas de trabalho operacionais, como detecção de fraudes ou personalização em tempo real. Isso requer configuração adicional e planejamento de compute. Consulte Usar o modo em tempo real em LakeFlow Pipelines.

Para obter mais informações, consulte Modo de pipeline Trigger vs. contínuo e Configurar pipelines.

Use clusters líquidos para disposição de dados

O agrupamento líquido substitui o particionamento estático e o ZORDER para otimizar a disposição de dados em tabelas Delta. O particionamento estático exige que você selecione colunas de partição e reorganize os dados antecipadamente, o que pode causar distorção nos dados para valores distribuídos de forma desigual. O agrupamento líquido é autoajustável, resistente a distorções e incremental, reescrevendo apenas os dados que precisam de reorganização em cada execução.

Altere as colunas de clustering a qualquer momento sem reescrever a tabela completa à medida que os padrões de query evoluem.

O Databricks recomenda o liquid clustering automático, que permite ao Databricks selecionar e manter as colunas de clustering ideais com base na sua carga de trabalho de query. Ative-o com CLUSTER BY AUTO:

SQL
CREATE OR REFRESH STREAMING TABLE events
CLUSTER BY AUTO
AS SELECT * FROM STREAM read_files("/volumes/raw/events", format => "parquet");

Para escolher as colunas de clustering por conta própria, especifique-as explicitamente:

SQL
CREATE OR REFRESH STREAMING TABLE events
CLUSTER BY (event_date, region)
AS SELECT * FROM STREAM read_files("/volumes/raw/events", format => "parquet");

Para obter mais informações, consulte Tabelas de transmissão e Usar clustering líquido para tabelas.

Gerenciar pipelines com CI/CD e Pacotes de Automação Declarativa

Faça o controle de versão do código-fonte do seu pipeline e use Pacotes de Automação Declarativa para gerenciar implantações em vários ambientes.

Para obter mais informações, consulte Criar um pipeline com controle de versão, Converter um pipeline em um projeto de pacote e Usar parâmetros com pipelines.

Armazene o código do pipeline no controle de versão.

Armazene todos os arquivos de código-fonte do pipeline (Python e SQL) junto com a configuração do seu bundle em um repositório Git. O controle de versão de todo o projeto oferece uma história completa das alterações, facilita a colaboração e permite validar as alterações em um ambiente de desenvolvimento antes de promovê-las para a produção.

O Databricks recomenda Pacotes de Automação Declarativa para gerenciar este fluxo de trabalho. Um bundle define a configuração do seu pipeline em YAML junto com seu código-fonte, e a CLI databricks bundle permite validar, implantar e executar pipelines a partir do seu terminal ou de um sistema de CI/CD.

Use alvos de pacote para isolamento de ambiente.

Os pacotes permitem vários destinos (por exemplo, dev, staging, prod), cada um com seu próprio conjunto de substituições para nomes de catálogo, políticas de cluster, endereços de notificação e outras configurações. Combine destinos de pacote com parâmetros de pipeline para injetar os valores corretos específicos do ambiente no momento da implantação, mantendo seu código-fonte livre de constantes de ambiente.

Um fluxo de trabalho típico tem a seguinte aparência:

  1. Um desenvolvedor trabalha em uma branch de recurso, implantando em um pipeline de desenvolvimento pessoal em um catálogo de dev.
  2. Ao fazer merge na branch principal, um sistema de CI executa databricks bundle validate e databricks bundle deploy --target staging para validar e implantar o pipeline em um ambiente de staging.
  3. Após a aprovação nos testes, o sistema de CI realiza a implantação na produção com databricks bundle deploy --target prod.

Práticas recomendadas de transmissão

Utilize estes padrões para gerenciar o estado, controlar dados atrasados e manter a confiabilidade dos pipelines de transmissão.

Para obter mais informações, consulte Otimizar o processamento com estado com marcas d'água, Recuperar um pipeline de falha de ponto de verificação de transmissão e Preenchimento de data histórica com pipelines.

Use marcas d'água para operações com estado

As marcas d'água limitam o estado que o pipeline mantém na memória durante operações de transmissão com estado, como agregações de janela e deduplicação. Sem uma marca d'água, o estado cresce sem limites à medida que o pipeline acumula dados para cada key possível, eventualmente causando erros de falta de memória em pipelines de longa execução.

Uma marca d'água especifica uma coluna de Timestamp e um limite de tolerância para dados atrasados. Os registros que chegam após o limite ter sido ultrapassado são descartados. Escolha um limite que equilibre sua tolerância a dados atrasados com o custo de memória de manter esse estado aberto.

O exemplo a seguir calcula uma agregação de janela rotativa de um minuto com uma marca d'água de três minutos:

SQL
CREATE OR REFRESH STREAMING TABLE event_counts AS
SELECT window(event_time, '1 minute') AS time_window, region, COUNT(*) AS cnt
FROM STREAM(events_raw)
WATERMARK event_time DELAY OF INTERVAL 3 MINUTES
GROUP BY time_window, region;
nota

Para garantir que as agregações sejam processadas incrementalmente, em vez de serem totalmente recalculadas a cada atualização, você deve definir uma marca d'água.

Entenda o estado de transmissão e o refresh completo

O estado da transmissão é incremental: o pipeline cria e mantém o estado entre as atualizações em vez de recalcular a partir do zero a cada vez. É isso que torna a transmissão com estado eficiente, mas também significa que, se você alterar a lógica de uma query com estado (por exemplo, modificando um limite de marca d'água ou alterando colunas de agregação), o estado existente não será mais compatível com a nova lógica. Nesse caso, você deve realizar um refresh completo para reprocessar toda a data histórica com a nova lógica e reconstruir o estado a partir do zero.

Um full refresh também pode levar à perda de dados se a fonte não reter dados históricos. Por exemplo, uma fonte Kafka com um curto período de retenção pode ter apenas os últimos minutos de dados disponíveis no momento do refresh, resultando em uma tabela que contém muito menos dados do que antes. Planeje cuidadosamente as alterações na lógica de queries com estado, especialmente para transmissões de alto volume, onde um refresh completo é dispendioso ou onde a fonte tem retenção de dados limitada. Utilizar a arquitetura de medalhão ajuda a criar tabelas de bronze com transformação mínima e permite que tabelas de prata ou ouro sejam recalculadas a partir das tabelas de bronze com histórico completo.

Joins de transmissão-transmissão

Joins de transmissão-transmissão exigem um watermark em ambos os lados do join e uma condição de join com limite de tempo. O intervalo de tempo na condição de join informa ao mecanismo de transmissão quando não são mais possíveis correspondências, permitindo que ele remova o estado que não pode mais ser correspondido. Se você omitir os watermarks ou a condição de limite de tempo, o estado crescerá sem limites.

O exemplo a seguir faz um join de eventos de impressão de anúncio com eventos de clique, exigindo que o clique ocorra dentro de três minutos da impressão:

SQL
CREATE OR REFRESH STREAMING TABLE impression_clicks AS
SELECT imp.ad_id, imp.impression_time, clk.click_time
FROM STREAM(ad_impressions)
WATERMARK impression_time DELAY OF INTERVAL 3 MINUTES AS imp
JOIN STREAM(user_clicks)
WATERMARK click_time DELAY OF INTERVAL 3 MINUTES AS clk
ON imp.ad_id = clk.ad_id
AND clk.click_time BETWEEN imp.impression_time
AND imp.impression_time + INTERVAL 3 MINUTES;

Ao fazer um join de uma transmissão com uma tabela estática (um snapshot join), o snapshot da tabela estática é atualizado no início de cada microbatch. Isso significa que registros de dimensão que chegam com atraso não são aplicados retroativamente a fatos que já foram processados. Se a aplicação retroativa for necessária, use uma view materializada ou reestruture o pipeline.

Otimizar o desempenho do pipeline

Aplique estas técnicas para reduzir os custos de compute e acelerar as atualizações de pipeline.

Para obter mais informações, consulte Materialized views e Otimizar o processamento com estado com marcas d'água.

Evite arquivos pequenos

Fazer o trigger de um pipeline com muita frequência em uma fonte de baixo volume grava um grande número de arquivos pequenos no armazenamento em cloud. Arquivos pequenos degradam o desempenho de leitura porque cada arquivo requer uma pesquisa de metadados separada e um round trip de E/S, e as APIs de armazenamento em cloud limitam as operações de listagem em escala. Para evitar isso, escolha um intervalo de Trigger que corresponda ao seu volume de dados: execute pipelines com Trigger em uma programar que permita que uma quantidade significativa de dados se acumule entre as atualizações, em vez de continuamente.

Lidar com a assimetria de dados

A distorção de dados ocorre quando os valores em uma **join** ou **key** de agrupamento são distribuídos de forma desigual entre as partições, fazendo com que um pequeno número de tarefas processe a maior parte dos dados. Isso cria pontos de acesso intenso que aumentam o tempo de atualização de ponta a ponta. Utilize o agrupamento líquido para corrigir a distorção em tabelas armazenadas. Para compensar a distorção que ocorre durante o processamento em tempo real, aplique um sufixo aleatório às chaves com alta distorção antes de agrupá-las e agregá-las em duas etapas.

Para obter mais informações, consulte Usar clustering líquido para disposição de dados.

Use incremental refresh para visualizações materializadas.

Ao usar uma view materializada para uma agregação grande, o pipeline tenta refresh incremental, processando apenas as alterações upstream desde a última atualização, em vez de recalcular todo o conjunto de resultados. O refresh incremental é significativamente mais barato do que executar novamente a query do zero a cada trigger de pipeline. Para maximizar a chance de uma view materializada poder ser atualizada incrementalmente, escreva queries de agregação simples e determinísticas e evite construções que impeçam o processamento incremental, como funções não determinísticas.

Consulte Refresh incremental para views materializadas.

Otimizar joins

Para junções em que um dos lados é uma tabela de dimensão pequena, adicione uma dica de transmissão para instruir o Spark a transmitir a tabela menor para todos os executores em vez de realizar uma junção aleatória (shuffle join):

SQL
CREATE OR REFRESH MATERIALIZED VIEW enriched_orders AS
SELECT o.*, /*+ BROADCAST(p) */ p.product_name, p.category
FROM orders o
JOIN products p ON o.product_id = p.product_id;

Para joins de séries temporais por proximidade (por exemplo, encontrar o evento mais próximo dentro de um intervalo de tempo), use uma condição de join por intervalo e certifique-se de que ambos os lados tenham uma marca d'água ao fazer join de transmissões, ou considere agrupar os eventos em intervalos de tempo antes do join.

Monitore seus pipelines

O registro de eventos do pipeline é o principal elemento primitivo de observabilidade em pipelines. Cada execução do pipeline grava registros estruturados no log de eventos, abrangendo o progresso da execução, os resultados esperados em relação à qualidade dos dados, a linhagem dos dados e os detalhes dos erros. O registro de eventos é uma tabela Delta que você pode query diretamente.

Para consultar o log de eventos sem saber o caminho de armazenamento subjacente, use a função event_log() com valor de tabela em um cluster compartilhado ou SQL Warehouse:

SQL
SELECT * FROM event_log('<pipeline-id>')
WHERE event_type = 'flow_progress'
ORDER BY timestamp DESC
LIMIT 100;

Crie painéis de qualidade de dados consultando o event log para obter as métricas de expectativa. A coluna details contém uma estrutura JSON aninhada com contagens de aprovação/reprovação para cada restrição, que você pode usar para acompanhar as tendências de qualidade ao longo do tempo e receber alertas sobre regressões.

Para alertas orientados a eventos, use ganchos de eventos para Trigger webhooks personalizados ou serviços de notificação (como Slack ou PagerDuty) quando um pipeline falhar ou quando um limite de qualidade de dados for violado. Ganchos de eventos são funções Python executadas em resposta a eventos de pipeline.

Para obter mais informações, consulte Monitorar pipelines, Log de eventos do pipeline e Definir monitoramento personalizado de pipelines com ganchos de eventos.

Usar compute serverless

O Databricks recomenda compute serverless para novos pipelines. Com o serverless, não há configuração manual de cluster; o Databricks gerencia a infraestrutura automaticamente. Os pipelines serverless usam autoscale aprimorado que pode escalar tanto horizontalmente (mais executors) quanto verticalmente (tamanho maior de executor) em resposta às demandas de carga de trabalho. Os pipelines serverless sempre usam o Unity Catalog, portanto, a governança e o acompanhamento de linhagem são integrados por default.

O Serverless também é necessário para refresh incremental de views materializadas. No compute clássico, as views materializadas são sempre totalmente recalculadas, o que aumenta os custos de refresh. Se o refresh incremental for importante para sua carga de trabalho, use compute serverless.

Para uma comparação entre compute serverless e classic, consulte Serverless vs. classic compute para pipelines. Para obter mais informações sobre serverless, consulte Configurar um pipeline serverless.

Organizar pipelines com a arquitetura medallion

A arquitetura medallion organiza os dados em três camadas lógicas (bronze, prata e ouro), cada uma com um propósito distinto. Mapear os tipos de dataset de pipeline para a camada correta mantém as responsabilidades de cada camada claras e torna os pipelines mais fáceis de manter.

  • Bronze : use tabelas de transmissão para ingerir dados brutos de armazenamento em cloud, barramentos de mensagens ou fontes de CDC. As tabelas bronze preservam os dados brutos de origem com transformação mínima, tornando possível que as camadas silver ou ouro reprocessam a partir da fonte na camada bronze caso os requisitos mudem.
  • Silver : Use tabelas de transmissão para transformações incrementais em nível de linha (filtragem, limpeza e análise). Use view materializadas quando a lógica da camada silver envolver join de enriquecimento em tabelas de dimensão ou agregações complexas que se beneficiam do refresh incremental.
  • Gold : use visualizações materializadas para pré-calcular agregações, métricas e resumos fornecidos a dashboards, ferramentas de relatório e consumidores downstream.

Separe a ingestão (bronze) e a transformação (silver e ouro) em pipelines distintos sempre que possível. O desacoplamento das camadas permite programar, monitorar e solucionar problemas de cada camada de forma independente, e uma falha em um pipeline de transformação não bloqueia a chegada de novos dados na camada bronze.

Para obter mais informações, consulte Tabelas de transmissão e Views materializadas.