SQL Academy · Aula

Tabelas de Fatos e Dimensões

Os blocos de construção de um armazém de dados.

Aula 2 de 413 etapas

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_email

Granularidade: 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 balance de 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.

Grátis para começar

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

  1. OLTP vs OLAP
  2. Tabelas de Fatos e Dimensões
  3. Esquemas Estrela e Floco de Neve
  4. Escrevendo Consultas Analíticas
← Voltar para SQL Academy