Tabelas de Fatos e Dimensões
Os blocos de construção de um armazém de dados.
Tabelas de Fatos e Dimensões é uma aula grátis de SQL Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Academy inclui 4 aulas no total.
O que é um armazém de dados?
Um armazém de dados é um repositório central projetado para relatórios e consultas analíticas. Diferentemente de um banco de dados transacional, otimizado para gravações rápidas, um armazém é ajustado para leituras rápidas em grandes volumes de dados históricos.
A maneira mais comum de organizar um armazém é usando um esquema estrela, que divide os dados em dois tipos de tabela: tabelas de fatos e tabelas de dimensões.
Definição de tabelas de fatos
Uma tabela de fatos armazena eventos mensuráveis e quantitativos — aquilo que você deseja analisar. Cada linha representa uma ocorrência de um evento de negócio, como uma venda, uma visualização de página da Web ou um chamado de suporte.
As tabelas de fatos normalmente são extensas (muitas linhas) e estreitas (poucas colunas), sendo que a maioria das colunas corresponde a chaves estrangeiras para tabelas de dimensões ou a medidas numéricas, como quantity ou revenue.
CREATE TABLE fact_sales (
sale_id SERIAL PRIMARY KEY,
date_key INT NOT NULL,
product_key INT NOT NULL,
customer_key INT NOT NULL,
store_key INT NOT NULL,
quantity INT NOT NULL,
unit_price NUMERIC(10, 2) NOT NULL,
total_amount NUMERIC(12, 2) NOT NULL
);Definição de tabelas de dimensões
Uma tabela de dimensões armazena atributos descritivos que fornecem contexto para cada fato. Os exemplos incluem uma dimensão de produto (nome, categoria, marca) ou uma dimensão de data (dia, mês, trimestre, ano).
As tabelas de dimensões geralmente são curtas (menos linhas), mas largas (muitas colunas descritivas). Elas são ligadas à tabela de fatos usando chaves substitutas inteiras.
CREATE TABLE dim_product (
product_key SERIAL PRIMARY KEY,
product_name VARCHAR(200) NOT NULL,
category VARCHAR(100),
brand VARCHAR(100),
unit_cost NUMERIC(10, 2)
);
CREATE TABLE dim_customer (
customer_key SERIAL PRIMARY KEY,
full_name VARCHAR(200) NOT NULL,
email VARCHAR(200),
country VARCHAR(100),
segment VARCHAR(50)
);A dimensão de data
A dimensão de data é a dimensão mais comum em qualquer armazém. Em vez de armazenar um TIMESTAMP bruto na tabela de fatos, você armazena uma chave inteira que referencia uma tabela de calendário criada previamente.
Isso permite que as consultas filtrem ou agrupem por trimestre fiscal, dia da semana, indicadores de feriado e outros atributos do calendário sem realizar cálculos de data no momento da consulta.
CREATE TABLE dim_date (
date_key INT PRIMARY KEY, -- e.g. 20240315
full_date DATE NOT NULL,
day_of_week VARCHAR(10),
day_of_month INT,
month_num INT,
month_name VARCHAR(20),
quarter INT,
year INT,
is_holiday BOOLEAN DEFAULT FALSE,
fiscal_quarter INT
);
-- Sample row
INSERT INTO dim_date VALUES
(20240315, '2024-03-15', 'Friday', 15, 3, 'March', 1, 2024, FALSE, 2);O padrão de esquema estrela
Quando você desenha um diagrama com uma tabela de fatos no centro e tabelas de dimensões irradiando para fora, ele se parece com uma estrela — daí o nome esquema estrela.
As chaves estrangeiras da tabela de fatos apontam para as chaves primárias de cada dimensão. As consultas normalmente fazem a junção da tabela de fatos com uma ou mais dimensões para adicionar contexto descritivo aos números brutos.
-- Join fact to two dimensions to enrich a sales report
SELECT
dp.product_name,
dp.category,
SUM(fs.quantity) AS total_units_sold,
SUM(fs.total_amount) AS total_revenue
FROM fact_sales fs
JOIN dim_product dp ON dp.product_key = fs.product_key
JOIN dim_date dd ON dd.date_key = fs.date_key
WHERE dd.year = 2024
GROUP BY dp.product_name, dp.category
ORDER BY total_revenue DESC;Chaves substitutas vs. chaves naturais
As tabelas de dimensões usam chaves substitutas — inteiros sintéticos gerados pelo banco de dados, independentes de qualquer significado de negócio. As chaves naturais (como um SKU de produto ou o email de um cliente) podem mudar com o tempo, mas as chaves substitutas nunca mudam.
O uso de chaves substitutas isola a tabela de fatos das alterações nos sistemas de origem e torna as junções mais rápidas, pois as comparações de inteiros são mais baratas que as comparações de cadeias de caracteres.
-- Surrogate key approach: integer join is fast
SELECT fs.sale_id, dc.full_name, fs.total_amount
FROM fact_sales fs
JOIN dim_customer dc ON dc.customer_key = fs.customer_key
WHERE dc.country = 'Germany'
LIMIT 10;
-- Natural key approach (avoid in warehouses): slower string join
-- JOIN dim_customer dc ON dc.email = fs.customer_emailGranularidade: nível de detalhe em uma tabela de fatos
A granularidade de uma tabela de fatos descreve exatamente o que uma linha representa. Antes de criar um armazém, você deve declarar a granularidade — por exemplo, uma linha para cada item individual de produto em um pedido de venda.
Uma granularidade bem definida evita agregações ambíguas. Se linhas diferentes representarem eventos diferentes, seus resultados de SUM e COUNT não terão sentido.
-- Grain: one row per product per order line
-- Each row = one line item sold in one transaction
SELECT
sale_id,
date_key,
product_key,
quantity,
unit_price,
total_amount
FROM fact_sales
WHERE date_key = 20240315
ORDER BY sale_id;Medidas aditivas, semiaditivas e não aditivas
Os fatos têm três tipos, de acordo com a maneira como podem ser agregados:
- Aditivos — podem ser somados em todas as dimensões (por exemplo,
revenue,quantity). - Semiaditivos — podem ser somados em algumas dimensões, mas não em todas (por exemplo, o
balancede uma conta pode ser somado entre clientes, mas não ao longo do tempo). - Não aditivos — não podem ser somados de maneira significativa (por exemplo,
unit_price,ratio). Use AVG ou outras agregações.
SELECT
dd.month_name,
SUM(fs.total_amount) AS total_revenue, -- additive
AVG(fs.unit_price) AS avg_unit_price, -- non-additive: use AVG
SUM(fs.quantity) AS total_units -- additive
FROM fact_sales fs
JOIN dim_date dd ON dd.date_key = fs.date_key
WHERE dd.year = 2024
GROUP BY dd.month_name, dd.month_num
ORDER BY dd.month_num;Dimensões de alteração lenta (SCD Tipo 1 e 2)
Os atributos das dimensões mudam ao longo do tempo — um cliente muda de país, um produto muda de categoria. As Dimensões de alteração lenta (SCD) lidam com essas mudanças:
- Tipo 1 — Substitui o valor antigo. É simples, mas o histórico é perdido.
- Tipo 2 — Adiciona uma nova linha com uma nova chave substituta e datas de validade. Preserva todo o histórico, para que os fatos históricos ainda apontem para a versão correta da dimensão.
-- SCD Type 2: add a new version of the row
ALTER TABLE dim_customer ADD COLUMN valid_from DATE;
ALTER TABLE dim_customer ADD COLUMN valid_to DATE;
ALTER TABLE dim_customer ADD COLUMN is_current BOOLEAN DEFAULT TRUE;
-- Expire the old row
UPDATE dim_customer
SET is_current = FALSE,
valid_to = CURRENT_DATE - INTERVAL '1 day'
WHERE email = 'anna@example.com' AND is_current = TRUE;
-- Insert the updated version
INSERT INTO dim_customer (full_name, email, country, segment, valid_from, valid_to, is_current)
VALUES ('Anna Muller', 'anna@example.com', 'Austria', 'Premium', CURRENT_DATE, '9999-12-31', TRUE);Dimensões degeneradas
Às vezes, um atributo de dimensão não precisa de sua própria tabela. Uma dimensão degenerada é uma chave de dimensão que reside diretamente na tabela de fatos, sem uma tabela de dimensões correspondente.
Exemplos clássicos são números de pedidos, números de faturas ou IDs de chamados. Eles fornecem contexto para o detalhamento, mas não têm outras colunas descritivas que valha a pena armazenar em uma tabela separada.
-- order_number is a degenerate dimension:
-- it lives in the fact table, no dim_order table needed
CREATE TABLE fact_order_lines (
line_id SERIAL PRIMARY KEY,
order_number VARCHAR(20) NOT NULL, -- degenerate dimension
date_key INT NOT NULL,
product_key INT NOT NULL,
customer_key INT NOT NULL,
quantity INT NOT NULL,
line_total NUMERIC(12, 2) NOT NULL
);
SELECT order_number, SUM(line_total) AS order_total
FROM fact_order_lines
GROUP BY order_number
ORDER BY order_total DESC
LIMIT 5;Consultando o esquema estrela completo
Reunindo tudo: uma consulta típica de armazém faz a junção da tabela de fatos com várias dimensões, aplica filtros aos atributos das dimensões e agrega as medidas da tabela de fatos.
O otimizador consegue lidar com eficiência com essas junções múltiplas porque as chaves estrangeiras da tabela de fatos estão indexadas e as tabelas de dimensões são relativamente pequenas.
SELECT
dd.year,
dd.quarter,
dp.category,
dc.country,
SUM(fs.quantity) AS units_sold,
SUM(fs.total_amount) AS revenue
FROM fact_sales fs
JOIN dim_date dd ON dd.date_key = fs.date_key
JOIN dim_product dp ON dp.product_key = fs.product_key
JOIN dim_customer dc ON dc.customer_key = fs.customer_key
WHERE dd.year IN (2023, 2024)
AND dp.category = 'Electronics'
GROUP BY dd.year, dd.quarter, dp.category, dc.country
ORDER BY dd.year, dd.quarter, revenue DESC;Verificação rápida: fatos vs. dimensões
Verifique sua compreensão das diferenças entre as tabelas de fatos e de dimensões em um esquema estrela.
Recapitulação da lição
Nesta lição, você aprendeu os blocos fundamentais de um esquema estrela de armazém de dados:
- As tabelas de fatos contêm eventos mensuráveis (vendas, cliques, transações), com medidas numéricas e chaves estrangeiras.
- As tabelas de dimensões fornecem contexto descritivo (quem, o quê, onde, quando) usando chaves substitutas.
- A granularidade define exatamente o que uma linha de fatos representa — declare-a antes de criar o armazém.
- As medidas são aditivas, semiaditivas ou não aditivas, o que determina como agregá-las.
- O SCD Tipo 2 preserva os valores históricos das dimensões adicionando novas linhas com datas de validade.
- As dimensões degeneradas residem na tabela de fatos quando não têm atributos adicionais para descrever.
Compreender as tabelas de fatos e de dimensões é a base para criar armazéns rápidos, escaláveis e poderosos para análises.
Aprenda SQL com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 46
- Aulas
- 183
Perguntas Frequentes
A aula “Tabelas de Fatos e Dimensões” é grátis?
Sim — o texto completo de “Tabelas de Fatos e Dimensões” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Academy, atualize para CoddyKit PRO. O curso de SQL Academy inclui 4 aulas no total.
O que vou aprender em “Tabelas de Fatos e Dimensões”?
Os blocos de construção de um armazém de dados. Você pratica SQL Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Academy?
Nenhuma experiência prévia é necessária. SQL Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Tabelas de Fatos e Dimensões”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Academy?
Sim. Cada aula de SQL Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- OLTP vs OLAP
- Tabelas de Fatos e Dimensões
- Esquemas Estrela e Floco de Neve
- Escrevendo Consultas Analíticas