SQL Academy · Les

Ster- en sneeuwvlokschema's

Modelleer gegevens voor snelle analyses

Les 3 van 413 stappen

Ster- en sneeuwvlokschema's is een gratis SQL Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject SQL Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus SQL Academy bevat in totaal 4 lessen.

Wat is een datawarehouseschema?

In een transactionele (OLTP-)database normaliseer je gegevens om redundantie te voorkomen. In een datawarehouse denormaliseer je gegevens vaak bewust — je ruilt opslagruimte in voor querysnelheid. Twee klassieke patronen voor het indelen van datawarehousetabellen zijn het sterschema en het sneeuwvlokschema.

Beide draaien rond een centrale feittabel met daaromheen dimensietabellen. Het verschil is hoever je die dimensies normaliseert.

Feittabellen en dimensietabellen

Een feittabel bevat meetbare gebeurtenissen — verkopen, klikken en verzendingen. De tabel is omvangrijk (veel rijen) en bevat numerieke meetwaarden plus vreemde sleutels naar dimensies.

Een dimensietabel beschrijft de context van elke gebeurtenis: wie, wat, wanneer en waar. Dimensies zijn kleiner (minder rijen), maar bevatten meer beschrijvende kolommen.

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,
  revenue      NUMERIC(12, 2) NOT NULL
);

CREATE TABLE dim_product (
  product_key  SERIAL PRIMARY KEY,
  product_name VARCHAR(200),
  category     VARCHAR(100),
  brand        VARCHAR(100),
  unit_price   NUMERIC(10, 2)
);

Het sterschema

In een sterschema is elke dimensietabel rechtstreeks verbonden met de feittabel. Teken de relaties op papier en het ziet eruit als een ster — de feittabel is het middelpunt en de dimensies zijn de punten.

Dimensietabellen zijn volledig gedenormaliseerd: alle beschrijvende attributen staan in één tabel, ook als sommige attributen in meerdere rijen worden herhaald.

-- Star schema: all product info in one flat dimension table
CREATE TABLE dim_product (
  product_key    SERIAL PRIMARY KEY,
  product_name   VARCHAR(200),
  category_name  VARCHAR(100),   -- denormalized
  subcategory    VARCHAR(100),   -- denormalized
  brand_name     VARCHAR(100),   -- denormalized
  brand_country  VARCHAR(100),   -- denormalized
  unit_price     NUMERIC(10, 2)
);

CREATE TABLE dim_date (
  date_key   INT PRIMARY KEY,   -- e.g. 20240315
  full_date  DATE,
  year       INT,
  quarter    INT,
  month      INT,
  month_name VARCHAR(20),
  week       INT,
  day_of_week VARCHAR(10)
);

Query voor het sterschema

Dankzij de vlakke dimensietabellen zijn query's eenvoudig. Je koppelt de feittabel aan een of meer dimensies en aggregeert de gegevens. Er zijn geen extra koppelingen via ketens van genormaliseerde tabellen.

Daarom leveren sterschema's snelle analytische query's — de koppelingsgrafiek is ondiep.

SELECT
  d.year,
  d.quarter,
  p.category_name,
  SUM(f.revenue)   AS total_revenue,
  SUM(f.quantity)  AS units_sold
FROM fact_sales f
JOIN dim_date    d ON d.date_key    = f.date_key
JOIN dim_product p ON p.product_key = f.product_key
WHERE d.year = 2024
GROUP BY d.year, d.quarter, p.category_name
ORDER BY d.quarter, total_revenue DESC;

Het sneeuwvlokschema

Een sneeuwvlokschema normaliseert dimensietabellen verder door ze op te splitsen in subdimensies. In plaats van bijvoorbeeld category_name en brand_name op te slaan in dim_product, maak je afzonderlijke tabellen dim_category en dim_brand.

Het resulterende diagram ziet eruit als een sneeuwvlok — vertakkende armen van gerelateerde tabellen.

-- Snowflake schema: product dimension is normalized
CREATE TABLE dim_brand (
  brand_key     SERIAL PRIMARY KEY,
  brand_name    VARCHAR(100),
  brand_country VARCHAR(100)
);

CREATE TABLE dim_category (
  category_key   SERIAL PRIMARY KEY,
  category_name  VARCHAR(100),
  subcategory    VARCHAR(100)
);

CREATE TABLE dim_product (
  product_key  SERIAL PRIMARY KEY,
  product_name VARCHAR(200),
  category_key INT REFERENCES dim_category(category_key),
  brand_key    INT REFERENCES dim_brand(brand_key),
  unit_price   NUMERIC(10, 2)
);

Query's op een sneeuwvlokschema

Voor het opvragen van gegevens uit een sneeuwvlokschema zijn meer joins nodig om dimensiegegevens die over meerdere tabellen zijn verdeeld weer samen te voegen. De query-optimizer moet de extra niveaus doorlopen, wat vergeleken met een sterschema extra latentie kan veroorzaken.

De genormaliseerde dimensies zijn echter kleiner en consistent — als je een merknaam in één rij van dim_brand bijwerkt, wordt die wijziging automatisch overal toegepast.

SELECT
  d.year,
  c.category_name,
  b.brand_name,
  SUM(f.revenue) AS total_revenue
FROM fact_sales    f
JOIN dim_date      d ON d.date_key    = f.date_key
JOIN dim_product   p ON p.product_key = f.product_key
JOIN dim_category  c ON c.category_key = p.category_key
JOIN dim_brand     b ON b.brand_key    = p.brand_key
WHERE d.year = 2024
GROUP BY d.year, c.category_name, b.brand_name
ORDER BY total_revenue DESC;

Surrogaatsleutels versus natuurlijke sleutels

Dimensietabellen gebruiken meestal een surrogaatssleutel — een door het datawarehouse gegenereerd geheel getal (bijvoorbeeld SERIAL) — in plaats van een natuurlijke sleutel uit het bronsysteem.

Surrogaatsleutels blijven stabiel, ook wanneer de bron verandert. Ze zijn compact voor grote feitentabellen en ondersteunen langzaam veranderende dimensies waarvan de geschiedenis moet worden bijgehouden.

-- Surrogate key (product_key) vs natural key (sku)
INSERT INTO dim_product (product_name, category_key, brand_key, unit_price)
VALUES ('Wireless Headphones', 3, 7, 89.99);
-- product_key is assigned by SERIAL -- the natural key (SKU) lives elsewhere

-- Natural key would be:
-- INSERT INTO dim_product (sku, product_name, ...)
-- VALUES ('WH-1000XM5', 'Wireless Headphones', ...);
-- Risky: SKU can be reused or reassigned by the source system

De datumdimensie

De datumdimensie is bijzonder — deze is vrijwel altijd aanwezig en wordt meestal vooraf gevuld met datums voor vele jaren. Door afgeleide kenmerken (jaar, kwartaal, maandnaam, boekhoudperiode, feestdagmarkering) in de dimensietabel op te slaan, hoef je ze niet opnieuw te berekenen wanneer je een query uitvoert.

-- Populate dim_date for one year using generate_series
INSERT INTO dim_date (date_key, full_date, year, quarter, month, month_name, week, day_of_week)
SELECT
  TO_CHAR(d, 'YYYYMMDD')::INT  AS date_key,
  d                             AS full_date,
  EXTRACT(YEAR    FROM d)::INT  AS year,
  EXTRACT(QUARTER FROM d)::INT  AS quarter,
  EXTRACT(MONTH   FROM d)::INT  AS month,
  TO_CHAR(d, 'Month')           AS month_name,
  EXTRACT(WEEK    FROM d)::INT  AS week,
  TO_CHAR(d, 'Day')             AS day_of_week
FROM generate_series('2024-01-01'::DATE, '2024-12-31'::DATE, '1 day') AS d;

Langzaam veranderende dimensies (SCD Type 2)

Wat gebeurt er wanneer een klant van stad verhuist of een product van categorie verandert? Je moet de geschiedenis bijhouden. SCD Type 2 voegt voor elke wijziging een nieuwe dimensierij toe en sluit de vorige rij af met een einddatum. De rij in de feitentabel verwijst nog steeds naar de oude dimensiesleutel, waardoor de historische nauwkeurigheid behouden blijft.

-- SCD Type 2 customer dimension
CREATE TABLE dim_customer (
  customer_key  SERIAL PRIMARY KEY,
  customer_id   INT NOT NULL,
  customer_name VARCHAR(200),
  city          VARCHAR(100),
  country       VARCHAR(100),
  valid_from    DATE NOT NULL,
  valid_to      DATE,
  is_current    BOOLEAN DEFAULT TRUE
);

-- When a customer moves, close old row and insert new one:
UPDATE dim_customer
   SET valid_to = CURRENT_DATE - 1, is_current = FALSE
 WHERE customer_id = 42 AND is_current = TRUE;

INSERT INTO dim_customer (customer_id, customer_name, city, country, valid_from, is_current)
VALUES (42, 'Alice Muller', 'Berlin', 'Germany', CURRENT_DATE, TRUE);

Sterschema versus sneeuwvlokschema — afwegingen

Geen van beide schema's is altijd beter. Kies op basis van je prioriteiten:

  • Ster — minder joins, snellere query's, eenvoudiger ETL en hogere opslagkosten. Het meest geschikt voor analysetools die veel lezen (Tableau, Power BI).
  • Sneeuwvlok — genormaliseerde dimensies, minder redundantie en eenvoudiger dimensies bijwerken, maar meer joins. Beter wanneer dimensies groot zijn of worden gedeeld door meerdere feitentabellen.
-- Checking how much storage the denormalized category column costs
-- in a large dim_product (star schema) vs a separate dim_category (snowflake)
SELECT
  COUNT(*)                               AS total_products,
  COUNT(DISTINCT category_name)          AS unique_categories,
  pg_size_pretty(
    SUM(pg_column_size(category_name))
  )                                      AS category_storage
FROM dim_product;

Galaxyschema (feitenconstellatie)

Wanneer een datawarehouse meerdere feitentabellen bevat die dimensietabellen delen, heet het resultaat een galaxyschema (of feitenconstellatie). Een datawarehouse voor detailhandel kan bijvoorbeeld afzonderlijke feitentabellen voor verkopen en retouren bevatten, die allebei verwijzen naar dim_product en dim_date.

Gedeelde dimensies zorgen voor consistente filters en maken vergelijkingen tussen feiten eenvoudig.

CREATE TABLE fact_returns (
  return_id     SERIAL PRIMARY KEY,
  date_key      INT NOT NULL REFERENCES dim_date(date_key),
  product_key   INT NOT NULL REFERENCES dim_product(product_key),
  customer_key  INT NOT NULL,
  quantity      INT NOT NULL,
  refund_amount NUMERIC(12, 2) NOT NULL
);

-- Cross-fact query: net revenue = sales - refunds
SELECT
  d.year,
  d.month,
  SUM(s.revenue)       AS gross_revenue,
  SUM(r.refund_amount) AS total_refunds,
  SUM(s.revenue) - COALESCE(SUM(r.refund_amount), 0) AS net_revenue
FROM dim_date d
LEFT JOIN fact_sales   s ON s.date_key = d.date_key
LEFT JOIN fact_returns r ON r.date_key = d.date_key
WHERE d.year = 2024
GROUP BY d.year, d.month
ORDER BY d.month;

Sterschema versus sneeuwvlokschema

Toets je begrip van ster- en sneeuwvlokschema's.

Lesoverzicht

In deze les heb je twee fundamentele ontwerppatronen voor datawarehouses verkend:

  • Sterschema — een centrale feitentabel, omringd door vlakke, gedenormaliseerde dimensietabellen. Minder joins, snellere query's en iets meer opslag.
  • Sneeuwvlokschema — dimensietabellen worden verder genormaliseerd tot subdimensies. Minder redundantie en eenvoudiger bijwerken, maar er zijn meer joins nodig.
  • Feitentabellen bevatten meetbare gebeurtenissen; dimensietabellen bieden context (wie, wat, wanneer, waar).
  • Surrogaatsleutels beschermen de historische nauwkeurigheid en ontkoppelen het datawarehouse van wijzigingen in het bronsysteem.
  • SCD Type 2 houdt de dimensiegeschiedenis bij door nieuwe rijen met geldigheidsdatums toe te voegen in plaats van oude rijen te overschrijven.
  • Wanneer meerdere feitentabellen dimensies delen, wordt het ontwerp een galaxyschema (feitenconstellatie).

Kies een ster voor eenvoud en snelheid; kies een sneeuwvlok wanneer dimensies groot zijn, vaak worden bijgewerkt of door veel feitentabellen worden gedeeld.

Gratis beginnen

Leer SQL met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
46
Lessen
183

Veelgestelde vragen

Is de les “Ster- en sneeuwvlokschema's” gratis?

Ja — de volledige tekst van “Ster- en sneeuwvlokschema's” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus SQL Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus SQL Academy bevat in totaal 4 lessen.

Wat leer ik in “Ster- en sneeuwvlokschema's”?

Modelleer gegevens voor snelle analyses Je oefent met SQL Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met SQL Academy te beginnen?

Ervaring vooraf is niet nodig. SQL Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Ster- en sneeuwvlokschema's”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over SQL Academy?

Ja. Elke les over SQL Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. OLTP versus OLAP
  2. Fact- en dimensietabellen
  3. Ster- en sneeuwvlokschema's
  4. Analytische query's schrijven
← Terug naar SQL Academy