◐ ai-teacher

❄️ Warehouse & Modeling · Chapter 3

Star vs snowflake schema

Same facts, same dimensions — the only question is whether a dimension is one flat table or a chain of little ones. The answer decides how many joins every dashboard pays for.

Study this lesson free in the app →

The basics

A star schema is a fact table joined directly to flat, denormalised dimension tables — draw it and it looks like a star. A snowflake schema normalises those dimensions further, so a dimension points to sub-dimensions (driver → vehicle → vehicle model; zone → city → state), and the diagram branches like a snowflake.

Why it matters: both store the same information. The choice trades storage and update simplicity (snowflake: each fact stored once) against query simplicity and speed (star: one join per dimension). Every BI tool, every analyst, every dashboard query lives with that choice daily.

The mental model: star = one hop from the fact to any attribute. Snowflake = several hops, each hop another join.

Words you must know 4

Denormalised
related attributes repeated in one table (city and state on every zone row).
Normalised
each fact stored once, linked by keys (state in its own table).
Outrigger
a dimension referenced by another dimension rather than by the fact.
Hierarchy
a chain like zone → city → state → region that you drill up and down.

Do not confuse the snowflake schema (a modelling shape from the 1990s) with Snowflake the product. You can build either shape in either database.

Explained

Meghalaya Cabs' analyst wants revenue by state.

In the star schema: fact_rides → dim_zone (state is a column). 1 join.

In the snowflake schema: fact_rides → dim_zone → dim_city → dim_district → dim_state. 4 joins, and one of them is an inner join on a city that was never mapped to a district — so ₹3.2 lakh of Tura revenue silently vanishes from the report.

The wedding seating chart

A wedding planner keeps a guest list.

Star version: one card per guest — name, table number, side (bride/groom), family, home town. The caterer reads one card and knows everything.

Snowflake version: the guest card says family #17. Family #17 is on another sheet, which says home town #4. Home town #4 is on a third sheet. Writing "Shillong" once instead of forty times saves ink.

But the caterer, at 9 pm with 300 guests, has to flip three sheets per plate. And if sheet three goes missing, a whole family has no seat.

That is the trade: write once vs read in one look.

The two shapes side by side

STAR                                SNOWFLAKE

 dim_date   dim_driver               dim_date   dim_driver ── dim_vehicle ── dim_model
      \       /                           \       /
      fact_rides                          fact_rides
      /       \                           /       \
 dim_rider   dim_zone                 dim_rider   dim_zone ── dim_city ── dim_state
             zone, city,
             state, region

revenue by state:                   revenue by state:
  fact → dim_zone      (1 join)       fact → zone → city → state  (3 joins)

The facts are identical. Only the dimensions changed shape.

What actually differs

                     STAR                        SNOWFLAKE
joins per attribute  1                           1 per hierarchy level
dim storage          repeated text (compressed)  each value once
rename a state       update every zone row       update one row
analyst SQL          short, hard to get wrong    longer, easy to drop rows
BI semantic layer    maps 1:1                    extra relationships
optimiser            1 small hash join per dim   more joins, more estimate error

In a columnar store, state = 'Meghalaya' repeated across 4,000 zone rows is dictionary/run-length encoded down to almost nothing. The storage win of snowflaking is close to zero — and dimensions are tiny next to facts anyway.

The same question, both ways

-- STAR: state lives on dim_zone
SELECT z.state, SUM(f.fare_inr) AS revenue_inr
FROM   fact_rides f
JOIN   dim_zone z ON z.zone_key = f.pickup_zone_key
GROUP  BY z.state;

-- SNOWFLAKE: walk the hierarchy
SELECT s.state_name, SUM(f.fare_inr) AS revenue_inr
FROM   fact_rides f
JOIN   dim_zone  z ON z.zone_key  = f.pickup_zone_key
JOIN   dim_city  c ON c.city_key  = z.city_key
JOIN   dim_state s ON s.state_key = c.state_key
GROUP  BY s.state_name;

-- Building the star dim FROM the normalised staging tables
CREATE OR REPLACE TABLE dim_zone AS
SELECT z.zone_key, z.zone_name, c.city_name AS city,
       s.state_name AS state, s.region
FROM   stg_zone z
LEFT JOIN stg_city  c ON c.city_id  = z.city_id
LEFT JOIN stg_state s ON s.state_id = c.state_id;

The LEFT JOINs are deliberate: flatten once, carefully, in the pipeline — so nobody writes a lossy inner join at query time.

Where each shape belongs

Normalisation is not wrong — it is just in the wrong place when it reaches the analyst.

When snowflaking earns its keep

Default to star. Snowflake a piece only when one of these is true:

At Meghalaya Cabs' scale (80k drivers, 4k zones) none of these apply. A star is faster to query, simpler to explain and cheaper to maintain.

Gotchas

Words to know

Star schemaA fact table joined directly to denormalised dimension tables, one join per dimension.
Snowflake schemaA dimensional model where dimensions are normalised into sub-dimension tables linked by keys.
DenormalisationDeliberately repeating related attributes in one table to avoid joins at read time.
OutriggerA secondary dimension referenced from another dimension instead of from the fact table.
HierarchyA many-to-one chain of attributes (zone → city → state → region) used to drill up and down.
Unknown memberA dimension row (often key -1) used when a lookup fails, so facts are never dropped by joins.

In two minutes

Test yourself

1. What distinguishes a snowflake schema from a star schema?

  1. Snowflake has more fact tables
  2. Snowflake normalises dimensions into sub-dimension tables
  3. Star cannot have a date dimension
  4. Snowflake schemas only run on Snowflake
Show the answer

Snowflake normalises dimensions into sub-dimension tables — The fact tables are the same; the difference is that a snowflake schema splits dimension hierarchies (zone → city → state) into separate linked tables.

2. Why has the storage argument for snowflaking mostly disappeared?

  1. Columnar warehouses compress repeated values very efficiently, and dimensions are small next to facts
  2. Cloud storage is free
  3. Snowflaking actually uses more storage
  4. Modern warehouses forbid normalised tables
Show the answer

Columnar warehouses compress repeated values very efficiently, and dimensions are small next to facts — Dictionary and run-length encoding make a value repeated thousands of times nearly free, and dimensions are tiny compared to fact tables. Cloud storage is cheap, not free.

3. Which layer is the most natural home for a normalised (3NF) shape?

  1. The BI semantic layer
  2. The gold/mart layer analysts query
  3. Staging/silver, mirroring the source
  4. Nowhere in a warehouse
Show the answer

Staging/silver, mirroring the source — Staging mirrors the source, which is usually normalised. Flattening happens on the way to the mart layer, so analysts get a star.

4. In the snowflake version, a report joins zone → city → district → state with INNER JOINs. 40 zones in Tura have no district mapped. What happens to their rides?

  1. They appear under state NULL
  2. The query fails
  3. They are silently dropped from the totals
  4. They are counted twice
Show the answer

They are silently dropped from the totals — An inner join drops rows with no match, so those rides vanish from every total. A flattened star dimension built with LEFT JOINs plus an 'Unknown' member keeps them visible.

5. Meghalaya Cabs has 40M riders; 2% are corporate accounts with 60 extra attributes. Where is snowflaking defensible?

  1. Splitting state out of dim_zone
  2. Splitting the corporate-account profile out of dim_rider
  3. Splitting fare out of fact_rides
  4. Splitting dim_date into dim_month and dim_year
Show the answer

Splitting the corporate-account profile out of dim_rider — A heavy, sparse sub-entity on a huge dimension is the classic justified case. Splitting state out of a 4k-row zone dim saves nothing and adds a join to every query.

6. A state is renamed. Which statement is accurate?

  1. Star: one row updated; snowflake: many rows
  2. Both require rebuilding the fact table
  3. Neither can handle renames
  4. Star: every zone row in that state is updated; snowflake: one row in dim_state
Show the answer

Star: every zone row in that state is updated; snowflake: one row in dim_state — This is the genuine advantage of normalisation: a single place to update. In a star you rewrite every dimension row carrying that state — a cheap pipeline job, but real.

There are 8 questions, 3 puzzles and 5 recall cards for this lesson in the app — the recall cards come back on later days, just before you would forget.

Learn it so it stays. Read it, test yourself, then recall it on two different days. The app schedules that for you, free.

Start this lesson →