À medida que as organizações consolidam as cargas de trabalho de análise para o Databricks, muitas vezes precisam adaptar técnicas tradicionais de armazém de dados. Esta série explora como implementar a modelagem dimensional - especificamente, esquemas estrela - no Databricks. O primeiro blog focou no design do esquema. Este blog percorre os pipelines ETL para tabelas de dimensão, incluindo Dimensões Lentamente Mutáveis (SCD) Tipo-1 e padrões Tipo-2. O último blog mostrará como construir pipelines ETL para tabelas de fatos.
No último blog, definimos nosso esquema estrela, incluindo uma tabela de fatos e suas dimensões relacionadas. Destacamos uma tabela de dimensão em particular, DimCustomer, como mostrado aqui (com alguns atributos removidos para economizar espaço):
Os três últimos campos nesta tabela, ou seja, StartDate, EndDate e IsLateArriving, representam metadados que nos auxiliam na versionamento de registros. À medida que a renda, estado civil, propriedade de casa, número de filhos em casa ou outras características de um determinado cliente mudam, queremos criar novos registros para esse cliente para que fatos como nossas transações de vendas online em FactInternetSales estejam associados à representação correta desse cliente. A chave natural (também conhecida como chave de negócio), CustomerAlternateKey, será a mesma em todos esses registros, mas os metadados serão diferentes, permitindo-nos saber o período em que essa versão do cliente era válida, assim como a chave substituta, CustomerKey, permitindo que nossos fatos se liguem à versão correta.
NOTA: Como a chave substituta é comumente usada para vincular fatos e dimensões, as tabelas de dimensão são frequentemente agrupadas com base nesta chave. Ao contrário dos bancos de dados relacionais tradicionais que utilizam índices b-tree em registros ordenados, o Databricks implementa um método de agrupamento único conhecido como agrupamento líquido. Embora os detalhes do agrupamento líquido estejam fora do escopo deste blog, usamos consistentemente a cláusula CLUSTER BY na chave substituta de nossas tabelas de dimensão durante sua definição para aproveitar efetivamente esse recurso.
Esse padrão de versionamento de registros de dimensão à medida que os atributos mudam é conhecido como o Padrão de Dimensão Lentamente Mutável Tipo-2 (ou simplesmente padrão SCD Tipo-2). O padrão SCD Tipo-2 é preferido para registrar dados de dimensão na metodologia dimensional clássica. No entanto, existem outras maneiras de lidar com mudanças nos registros de dimensão.
Uma das maneiras mais comuns de lidar com a mudança de valores de dimensão é atualizar os registros existentes no local. Apenas uma versão do registro é criada, de modo que a chave de negócio permanece como o identificador único para o registro. Por vários motivos, não menos importante são desempenho e consistência, ainda implementamos uma chave substituta e vinculamos nossos registros de fato a essas dimensões nessas chaves. Ainda assim, os campos de metadados DataInicial e DataFinal que descrevem os intervalos de tempo durante os quais um determinado registro de dimensão é considerado ativo não são necessários. Isso é conhecido como o padrão SCD Tipo-1. A dimensão Promoção em nosso esquema estrela fornece um bom exemplo de uma implementação de tabela de dimensão Tipo-1:
Mas e o campo IsLateArriving de metadados visto na dimensão do Cliente do Tipo-2, mas ausente na dimensão da Promoção do Tipo-1? Este campo é usado para marcar registros como chegadas tardias. Um registro de chegada tardia é aquele para o qual a chave de negócio aparece durante um ciclo ETL de fatos, mas não há registro para essa chave localizado durante o processamento de dimensão anterior. No caso dos SCDs do Tipo-2, este campo é usado para denotar que quando os dados para um registro de chegada tardia são observados pela primeira vez em um ciclo ETL de dimensão, o registro deve ser atualizado no local (assim como em um padrão SCD do Tipo-1) e então versionado a partir desse ponto. No caso dos SCDs do Tipo-1, este campo não é necessário porque o registro será atualizado no local, independentemente.
NOTA: O Grupo Kimball reconhece padrões SCD adicionais, a maioria dos quais são variações e combinações dos padrões Tipo-1 e Tipo-2. Como os SCDs Tipo-1 e Tipo-2 são os mais frequentemente implementados desses padrões e as técnicas usadas com os outros estão intimamente relacionadas ao que é empregado com estes, estamos limitando este blog a apenas esses dois tipos de dimensão. Para mais informações sobre os oito tipos de SCDs reconhecidos pelo Grupo Kimball, consulte a seção Técnicas de Dimensão Lentamente Mutável deste documento.
Com os dados sendo atualizados no local, o padrão de fluxo de trabalho SCD Tipo-1 é o mais direto dos padrões ETL bidimensionais. Para suportar esses tipos de dimensões, simplesmente:
Para ilustrar uma implementação SCD Tipo-1, definiremos o ETL para o preenchimento contínuo da tabela DimPromotion.
Nosso primeiro passo é extrair os dados de nosso sistema operacional. Como nosso data warehouse é baseado no banco de dados de exemplo AdventureWorksDW fornecido pela Microsoft, estamos usando o banco de dados de exemplo AdventureWorks (OLTP) como nossa fonte. Este banco de dados foi implantado em uma instância do Azure SQL Database e tornou-se acessível em nosso ambiente Databricks por meio de uma consulta federada. A extração é então facilitada com uma simples consulta (com alguns campos redigidos para economizar espaço), com os resultados da consulta persistidos em uma tabela em nosso esquema de staging (que é acessível apenas para os engenheiros de dados em nosso ambiente através de configurações de permissão não mostradas aqui). Esta é apenas uma das muitas maneiras que podemos acessar os dados do sistema de origem neste ambiente:
Supondo que não temos etapas adicionais de limpeza de dados para realizar (que poderíamos implementar com um UPDATE ou outro comando CREATE TABLE AS), podemos então lidar com nossas operações de atualização/inserção de dados de dimensão em uma única etapa usando um comando MERGE, combinando nossos dados em estágio e dados de dimensão na chave de negócio:
Uma coisa importante a notar sobre a declaração, como foi escrita aqui, é que atualizamos quaisquer registros existentes quando uma correspondência é encontrada entre os dados da tabela de dimensão em estágio e publicada. Poderíamos adicionar critérios adicionais à cláusula WHEN MATCHED para limitar as atualizações àquelas instâncias em que um registro em estágio tem informações diferentes do que é encontrado na tabela de dimensão, mas, dado o número relativamente pequeno de registros nesta tabela específica, optamos por empregar a lógica relativamente mais enxuta mostrada aqui. (Usaremos a lógica adicional WHEN MATCHED com DimCustomer, que contém muito mais dados.)
O padrão SCD do tipo 2 é um pouco mais complexo. Para suportar esses tipos de dimensões, devemos:
Como no padrão SCD Tipo-1, nossos primeiros passos são extrair e limpar os dados do sistema de origem. Usando a mesma abordagem acima, emitimos uma consulta federada e persistimos os dados extraídos em uma tabela em nosso staging schema:
Com esses dados carregados, agora podemos compará-los com nossa tabela de dimensão para fazer quaisquer modificações de dados necessárias. A primeira delas é atualizar no local quaisquer registros marcados como chegadas tardias de processos ETL de tabela de fatos anteriores. Por favor, note que essas atualizações são limitadas àqueles registros marcados como chegadas tardias e a IsLateArriving flag está sendo redefinida com a atualização para que esses registros se comportem como SCDs do Tipo-2 normais daqui para frente:
O próximo conjunto de modificações de dados é para expirar quaisquer registros que precisam ser versionados. É importante que o EndDate valor que definimos para estes corresponda ao StartDate da nova versão do registro que implementaremos na próxima etapa. Por essa razão, definiremos um timestamp variável para ser usado entre essas duas etapas:
NOTA: Dependendo dos dados disponíveis para você, pode optar por usar um valor EndDate originário do sistema de origem, momento em que não necessariamente declararia uma variável como mostrado aqui.
Por favor, note os critérios adicionais usados na cláusula WHEN MATCHED. Como estamos realizando apenas uma operação com esta declaração, seria possível mover essa lógica para a cláusula ON, mas a mantivemos separada da lógica de correspondência central, onde estamos correspondendo à versão atual do registro de dimensão para clareza e manutenibilidade.
Como parte desta lógica, estamos fazendo uso intensivo da função equal_null(). Esta função retorna TRUE quando o primeiro e o segundo valores são iguais ou ambos NULL; caso contrário, retorna FALSE. Isso fornece uma maneira eficiente de procurar mudanças em uma base de coluna por coluna. Para mais detalhes sobre como o Databricks suporta semântica NULL, consulte este documento.
Nesta etapa, quaisquer versões anteriores de registros na tabela de dimensão que expiraram foram datadas para o fim.
Agora podemos inserir novos registros, tanto verdadeiramente novos quanto recém-versionados:
Como antes, isso poderia ter sido implementado usando uma declaração INSERT, mas o resultado é o mesmo. Com esta declaração, identificamos quaisquer registros na tabela de estágio que não têm um registro correspondente não expirado nas tabelas de dimensão. Esses registros são simplesmente inseridos com um valor StartDate consistente com quaisquer registros expirados que possam existir nesta tabela.
Com as dimensões implementadas e preenchidas com dados, agora podemos nos concentrar nas tabelas de fatos. No próximo blog, demonstraremos como o ETL para essas tabelas pode ser implementado.
Para saber mais sobre o Databricks SQL, visite nosso website ou leia a documentação. Você também pode conferir o tour do produto Databricks SQL. Suponha que você queira migrar seu armazém existente para um armazém de dados sem servidor de alto desempenho, com uma ótima experiência do usuário e um custo total mais baixo. Nesse caso, o Databricks SQL é a solução — experimente gratuitamente.
(This blog post has been translated using AI-powered tools) Original Post