Como criar uma Fact table de tipo 'Periodic Snapshot' em Modelação de Dados (Kimball)
Este tutorial ensina a criar uma Fact table do tipo Periodic Snapshot em Modelação de Dados (Kimball) para armazenar métricas periódicas (por exemplo, saldo diário de conta). A Periodic Snapshot é útil para relatórios de tendência e reconciliação quando os eventos não capturam o estado em cada período.
Pré-requisitos
- Conhecimentos básicos de SQL (SELECT, JOIN, GROUP BY).
- Entendimento de conceitos Kimball: fact tables, dimension tables, chaves surrogate.
- Uma base de dados para testes (ex.: SQL Server, PostgreSQL) com tabelas de origem.
Passo 1: Definir o objetivo e a granularidade
Explique por que precisa de uma Periodic Snapshot: quer registar o estado no final de cada dia, semana ou mês? A granularidade determina as dimensões da fact e a frequência de carga. Decida também quais métricas são snapshots (por exemplo, saldo, número de utilizadores activos) e quais são acumuladas.
Passo 2: Identificar dimensões e chave de grain
Escolha as dimensões que descrevem o grain. Para um snapshot diário de conta, o grain pode ser: um registo por data + account_id. As dimensões comuns: DimDate, DimAccount, DimBranch, DimProduct. Crie ou confirme as surrogate keys das dimensões.
Passo 3: Esquema da Periodic Snapshot fact table
Defina colunas: surrogate keys para dimensões, snapshot_date, métricas (saldo, número de transacções no dia) e indicadores (flags). Inclua colunas de auditoria (load_date, source_system).
CREATE TABLE FactAccountDailySnapshot (
FactSnapshotSK BIGINT IDENTITY(1,1) PRIMARY KEY,
DateSK INT NOT NULL,
AccountSK INT NOT NULL,
BranchSK INT NULL,
SnapshotDate DATE NOT NULL,
Balance DECIMAL(18,2) NULL,
DailyTxCount INT NULL,
LoadDate DATETIME NOT NULL DEFAULT GETDATE(),
SourceSystem VARCHAR(50) NULL
);
Passo 4: Mapear fontes e calcular estado por período
Identifique as tabelas fonte e a lógica para calcular o estado no fim do período. Por exemplo, calcular o saldo diário pode somar transacções até ao fim do dia ou usar uma coluna de saldo corrente se existir.
-- Exemplo: calcular saldo por account no fim do dia somando transacções
WITH TxUntilDay AS (
SELECT
account_id,
CAST(transaction_date AS DATE) AS txn_date,
SUM(amount) AS day_amount
FROM StgTransactions
WHERE transaction_date <= @SnapshotDate + '23:59:59'
GROUP BY account_id, CAST(transaction_date AS DATE)
)
SELECT a.account_id, d.DateSK, a.AccountSK,
ISNULL(t.day_amount,0) AS Balance -- simplificação de exemplo
FROM DimAccount a
CROSS JOIN (SELECT @SnapshotDate AS SnapshotDate, DateSK FROM DimDate WHERE FullDate = @SnapshotDate) d
LEFT JOIN TxUntilDay t ON t.account_id = a.account_id AND t.txn_date = @SnapshotDate;
Passo 5: Estratégia de carga (ETL/ELT)
Decida se faz carga completa diária (recria os registos desse dia) ou incremental (apaga/regenera por grain). A abordagem mais segura para snapshots é carregar por período: eliminar registos de SnapshotDate e grain e inserir os novos. Automatize com transacções para atomicidade.
BEGIN TRANSACTION;
DELETE FROM FactAccountDailySnapshot
WHERE SnapshotDate = @SnapshotDate;
INSERT INTO FactAccountDailySnapshot (DateSK, AccountSK, BranchSK, SnapshotDate, Balance, DailyTxCount, SourceSystem)
SELECT d.DateSK, a.AccountSK, a.BranchSK, @SnapshotDate, t.Balance, t.DailyTxCount, 'OLTP'
FROM (... cálculo anterior ...) t
JOIN DimAccount a ON a.account_id = t.account_id
JOIN DimDate d ON d.FullDate = @SnapshotDate;
COMMIT;
Passo 6: Lidar com erros comuns
Erros frequentes: 1) grain mal definido (duplicados por SnapshotDate/account); 2) não utilizar surrogate keys das dimensões; 3) carga parcial sem limpeza causando valores antigos; 4) performance na junção com tabelas grandes. Para evitar, implemente constraints de unicidade (DateSK+AccountSK+SnapshotDate), índices e partição por SnapshotDate se suportado.
ALTER TABLE FactAccountDailySnapshot
ADD CONSTRAINT UQ_FactSnapshot_Date_Account UNIQUE (DateSK, AccountSK, SnapshotDate);
-- Índice para melhorar consultas por data
CREATE INDEX IX_FactAccountDailySnapshot_SnapshotDate ON FactAccountDailySnapshot(SnapshotDate);
Verificar o resultado
Valide integridade e valores: 1) confirmar unicidade por grain; 2) reconciliar somas agregadas com sistemas fonte para várias datas; 3) testar query de tendência (ex.: saldo por account nos últimos 30 dias). Exemplos de checks em SQL:
-- 1. Verificar duplicados
SELECT DateSK, AccountSK, SnapshotDate, COUNT(*)
FROM FactAccountDailySnapshot
GROUP BY DateSK, AccountSK, SnapshotDate
HAVING COUNT(*) > 1;
-- 2. Reconciliar total de saldo (amostra)
SELECT f.SnapshotDate, SUM(f.Balance) AS TotalBalance
FROM FactAccountDailySnapshot f
WHERE f.SnapshotDate BETWEEN '2026-07-01' AND '2026-07-31'
GROUP BY f.SnapshotDate
ORDER BY f.SnapshotDate;
Conclusão
Uma Periodic Snapshot em Modelação de Dados (Kimball) captura estados regulares para análises de tendência e auditoria. Próximos passos: agregar outras métricas, particionar a tabela para escala e automatizar a carga com um scheduler. Dica: começa com cargas diárias em ambiente de teste e verifica sempre as reconciliações antes de produção — qual métrica queres capturar primeiro?