C.W.K.
Stream
Lesson 02 of 05 · published

Star vs Snowflake — When and Why

~9 min · modeling, schema, kimball

Level 0Curious Reader
0 XP0/47 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The two layouts

  • Star schema. Each dimension is a single denormalized table. dim_customers contains name, country, region, segment all in one row. The shape on a diagram is a fact table in the middle with dimensions radiating outward — hence "star."
  • Snowflake schema. Dimensions are normalized further. dim_customers has a region_key; dim_regions has a country_key; dim_countries sits beyond that. The shape is a fact table with dimensions branching into sub-dimensions — hence "snowflake."

The unsexy truth

For analytics work, star wins almost every time. The reasons:

  • Fewer joins per query → faster execution and clearer SQL.
  • BI tools generate cleaner queries against star schemas.
  • Denormalized dimensions are easier to mentally model.
  • Storage is cheap; the extra space the denormalization costs is negligible compared to the readability win.

Snowflake schemas have a place — when a sub-dimension is huge and changes independently, breaking it out can be the right call. But the default for a new analytics warehouse is a star schema, and you should snowflake only when the specific cost-of-keeping-it-flat justifies it.

Code

Same dimension, two layouts·sql
-- Star: one denormalized customer dimension
CREATE TABLE dim_customers (
    customer_key  INTEGER PRIMARY KEY,
    customer_id   TEXT NOT NULL,
    name          TEXT,
    region_code   TEXT,                         -- 'KR', 'US', 'JP'
    region_name   TEXT,                         -- 'Korea', 'United States', 'Japan'
    continent     TEXT                          -- 'Asia', 'North America'
);

-- Snowflake: customers links to regions, regions links to continents
CREATE TABLE dim_customers_snow (
    customer_key  INTEGER PRIMARY KEY,
    customer_id   TEXT NOT NULL,
    name          TEXT,
    region_key    INTEGER REFERENCES dim_regions(region_key)
);
CREATE TABLE dim_regions (
    region_key    INTEGER PRIMARY KEY,
    region_code   TEXT NOT NULL,
    region_name   TEXT,
    continent_key INTEGER REFERENCES dim_continents(continent_key)
);
CREATE TABLE dim_continents (
    continent_key INTEGER PRIMARY KEY,
    name          TEXT NOT NULL
);

-- Querying revenue by continent:
--   star:  fact JOIN dim_customers              (1 join)
--   snow:  fact JOIN dim_customers_snow JOIN dim_regions JOIN dim_continents (3 joins)

External links

Exercise

For the dimensional model you sketched in the previous exercise, decide for each dimension: star or snowflake? Justify in one sentence per dimension. The exercise is to practice the reflex — defaulting to star, and being explicit when a snowflake is worth it.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.