Como montar um modelo dimensional que não quebre no dia a dia
A maioria dos projetos de data warehouse começa com uma confusão básica entre os dois tipos de tabela e só se percebe o problema quando a query já está lenta demais para ser útil. A separação entre tabela fato e tabela dimensão parece simples na teoria, mas na prática envolve decisões de design que comprometem tudo depois se forem erradas desde o início.
A diferença entre tabela fato e tabela dimensão e como usá-las
A tabela fato armazena eventos mensuráveis — vendas, saques, cliques, chamadas técnicas. Cada linha representa algo que aconteceu num momento específico, com números que podem ser somados, médios ou contados. A tabela dimensão guarda os atributos descritivos desses eventos: produto, cliente, data, loja, canal. A junção acontece pela chave estrangeira. A dimensão aponta para a fato com uma surrogate key, e a fato referencia a dimensão. Isso permite que os atributos descritivos sejam normalizados e reutilizados em múltiplos contextos sem duplicar informação.
No meu caso, trabalhei num projeto de varejo onde a dimensão de produto tinha cerca de 400 mil registros e a tabela fato de vendas movia aproximadamente 2,3 bilhões de linhas por ano. O ETL precisava fazer o lookup de cada produto a cada registro de venda. O banco ficava preso em joins sequenciais que levavam horas. A solução foi criar um index bitmap na chave estrangeira da tabela fato e particionar a fato por trimestre. O tempo de processamento caiu de algo em torno de 4 horas para cerca de 25 minutos, dependendo do período consultado.
Decisões de modelagem que quase ninguém menciona
O primeiro erro comum é transformar atributos de dimensão em colunas da tabela fato. Parece conveniente na hora de consultar, porque evita joins, mas você cria redundância massiva e problemas de atualização em cascata. Se o nome de uma categoria de produto muda, você precisa atualizar todas as linhas da fato que o referenciam. Em tabelas grandes, isso vira um pesadelo de locks e performance. Outro erro frequente é criar uma dimensão degenerada para cada código de transação. Um número de nota fiscal ou número de pedido não precisa de uma tabela dimensão separada. Esses atributos degenerados pertencem diretamente à tabela fato como colunas textuais. Achar que tudo precisa de sua própria dimensão é uma armadilha que gera dezenas de tabelas inúteis e consulta mais lenta.
Dimensiones lentas do tipo change-tracking, também chamadas de Type 2 SCD, merecem atenção especial. Elas mantêm histórico de alterações nos atributos, adicionando novas linhas com períodos de validade. Funcionam bem para dados de clientes e categorias, mas se você aplicar esse tipo em dimensões muito grandes ou com taxa de mudança altíssima, a tabela fato vai crescer junto porque cada evento precisa saber qual versão da dimensão era válida naquele momento. Testei isso com uma dimensão de funcionário que tinha 15 mil linhas e taxa de rotatividade de 30% ao ano. Em três anos, a versão histórica explodiu para mais de 200 mil linhas, e o join tornou-se significativamente mais pesado.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Como estruturar a tabela fato na prática
Divida as colunas da fato em três grupos: chaves estrangeiras que ligam às dimensões, medidas aditivas que podem ser somadas globalmente, e medidas semi-aditivas ou não aditivas quando necessário. Medidas como saldo de conta ou preço em estoque são semi-aditivas — somam dentro de uma dimensão (tempo), mas não entre outras (produto, loja). Escolha granularidade com cuidado. Uma tabela fato de nível transacional, linha de venda, concentra muito mais dados que uma fato consolidada por dia. Se o negócio não exige detalhe operacional, uma fato resumida por dia reduz drasticamente o volume e melhora performance sem perder informação relevante para a maioria das consultas.
O formato de armazenamento também importa. Dados colunares, como ColumnStore, costumam reduzir o tamanho físico em fatores de três a dez vezes comparado ao formato row-based tradicional, e aceleram consultas analíticas em escala similar. A desvantagem é que inserções em lote e atualizações pontuais ficam mais caras, então esse formato se encaixa melhor em cenários de carga periódica e leitura intensiva.
Quando o modelo dimensional tradicional não funciona
Sistemas transacionais com alta frequência de escrita e necessidade de consistência imediata não se beneficiam de um modelo dimensional puro. O overhead de manter dimensões lentas, surrogate keys e camadas de staging consome recurso que seria melhor direcionado a Indexes B-tree convencionais e constraints otimistas. Nesses casos, um modelo normalizado 3FN com partições estratégicas e materialized views para as consultas mais pesadas entrega resultado comparable com muito menos complexidade. Também há situações em que uma star schema simples se torna insuficiente. Relacionamentos muitos-para-muitos entre fatos e dimensões, fenômenos de grão misturado na mesma fonte, e fontes de dados com esquema flexível e campos variáveis exigem abordagens diferentes. Aqui, o Data Vault ou o modelo de esqueleto de fatos (Fact Constellation com múltiplas tabelas fato compartilhando dimensões) são opções mais adequadas, embora introduzam complexidade adicional de engenharia.
Passo a passo para começar
Primeiro, mapeie os processos de negócio como eventos mensuráveis. Identifique o que é mensurável e o que é descritivo. Segredo: anote também o que pode mudar ao longo do tempo nos atributos descritivos, porque isso define o tipo de dimensão que você vai construir. Depois, modele as dimensões com surrogate keys numéricas. Evite usar chaves naturais do sistema de origem como referência na tabela fato — elas mudam, se repetem e causam inconsistência quando fontes diferentes são integradas.
Construa a tabela fato com as chaves estrangeiras para todas as dimensões relevantes e as medidas associadas ao evento. Aplique a granularidade mais detalhada que o negócio realmente precisa, não a mais detalhada possível. Implemente a carga em lotes com tratamento de erros e logging. Registre quantos registros foram processados, quantos falharam e quais chaves de dimensão não foram encontradas. Eu perdi uma semana rastreando valores nulos que pareciam válidos porque a dimensão de canal não tinha sido populada para um subcanal específico de e-commerce antes do go-live.
Documente o dicionário de dados com origem, fórmula de cálculo das medidas, e periodicidade de atualização. Sem isso, qualquer pessoa que chegar depois vai reinterpretar métricas existentes de formas diferentes, e você terá duas versões da verdade no mesmo dashboard. O custo de manutenção de um modelo dimensional bem feito tende a diminuir com o tempo, porque novas consultas reaproveitam estruturas existentes. Um modelo mal construído aumenta de custo exponencialmente a cada nova demanda, porque cada ajuste requer reexaminar joins, revalidar agregações e verificar se as mudanças na dimensão não quebraram fatos históricos já carregados. A diferença entre esses dois caminhos está nas primeiras decisões de design.