Snowflake Schema

Example, vs Star Schema and When to Use It

A snowflake schema is a data warehouse model in which a central fact table joins to dimensions that are normalized into chains of tables, product to subcategory to category for example, instead of 1 flat table each. It stores every hierarchy value once in exchange for extra joins, and on a columnar warehouse the storage it saves is usually negligible, so most teams keep dimensions flat and snowflake only a hierarchy that is maintained on its own.

Last updated: Proudly published by: Jeff Wahl13 min read

What is a snowflake schema?

A snowflake schema is a dimensional data model in which a fact table records the business events and at least 1 of the dimensions around it is normalized into a chain of tables. In a star schema, dim_product holds the product name next to the names of its subcategory and category. Snowflake that dimension and the subcategory and category move to dim_subcategory and dim_category, each linked to the level beneath it by a key, so every name is stored once.

Drawn as a diagram, the dimensions branch outward from the fact table in 2 or 3 levels instead of 1, which gives the model its shape and its name. The Kimball Group's definition of a snowflaked dimension says that low-cardinality attributes of a hierarchy become secondary tables connected to the base dimension by an attribute key, and that repeating this for every hierarchy produces the multilevel structure. The same entry notes that a flattened dimension contains exactly the same information as the snowflaked one. Snowflaking changes where values are stored and how many joins reach them, never what the data warehouse can answer.

A snowflake stores each hierarchy value once and gives each level its own table to maintain. It pays for that with extra joins on every query that reads the upper levels, and with more tables for analysts to learn.

A snowflake schema example: retail sales

fact_sales
sale_line_idPKBIGINT
date_keyFKINT
product_keyFKINT
store_keyFKINT
quantityINT
net_amountDECIMAL
dim_date
date_keyPKINT
calendar_dateDATE
fiscal_monthVARCHAR
dim_product
product_keyPKINT
product_nameVARCHAR
subcategory_keyFKINT
dim_subcategory
subcategory_keyPKINT
subcategory_nameVARCHAR
category_keyFKINT
dim_category
category_keyPKINT
category_nameVARCHAR
dim_store
store_keyPKINT
store_nameVARCHAR
city_keyFKINT
dim_city
city_keyPKINT
city_nameVARCHAR
country_codeVARCHAR

1 row of fact_sales per sale line. dim_date is a flat star dimension; the product hierarchy is snowflaked 3 levels deep and the store's geography 2 levels deep, each level holding its own key and the key of the level above.

How a snowflake data model is built from a star

Start from a flat dimension and look for columns that depend on another column rather than on the dimension's key. In dim_product, category_name depends on subcategory_name: every product in Laptops sits in Computers. That dependency is a many-to-one hierarchy, and snowflaking moves each level to its own table with a surrogate key, leaving only the key of the parent level on each child table. The product row keeps subcategory_key; the subcategory row keeps category_key.

The fact table does not change. It still carries 1 foreign key per dimension and the measures at its grain, so fact grain and conformed dimensions work as before, and the slowly changing dimension rules of dimensional modeling still apply. Only the distance from the fact table to an attribute grows: a category is now 3 tables away.

The best-known snowflake schema in the field is a benchmark. The TPC-DS specification, the Transaction Processing Performance Council's decision support benchmark, states in clause 1.3.3 that its schema is a snowflake schema: 7 fact tables and 17 dimension tables, each dimension with a single column surrogate key. Its household_demographics dimension points to an income_band table, and customer points to customer_address and customer_demographics. The fact tables also carry those keys directly, a hybrid that keeps the most common filters 1 join away while the hierarchy stays normalized.

Prepare for the interview
01 / Open invite
02min.

Know Snowflake Schema the way the interviewer who asks it knows it.

a Snowflake Schema query, the same shape a screen would give you.
The diff against expected. Where ties broke. What you missed.
sandbox
1fact_orders
2 order_id bigint PK
3 customer_sk bigint FK
4 order_date date SCD2
5
Execute your solution0.4s avg.
AirbnbInterview question
Solve a Snowflake Schema problem

How many joins a snowflake schema adds

Every level of a hierarchy that moves to its own table adds 1 join for any query that reads it. Revenue by category takes 1 join in the star schema, fact to product, because category_name sits on dim_product. In the snowflake it takes 3: fact to product, product to subcategory, subcategory to category, even though the query needs nothing from the 2 tables in the middle.

Join path from fact_sales to category_name: in the star schema dim_product holds category_name, 1 join away; in the snowflake schema the path runs through dim_product and dim_subcategory to dim_category, 3 joins awayJoin path from fact_sales to category_name: in the star schema dim_product holds category_name, 1 join away; in the snowflake schema the path runs through dim_product and dim_subcategory to dim_category, 3 joins away

Each of those joins is cheap on its own, because dimension tables are small and the engine hashes them into memory. The cost adds up across the model. A query that groups by fiscal month and store country as well as category now plans 6 joins instead of 3, and an analyst has to know which of 7 tables holds country_code while a BI semantic layer has to model every hop. Microsoft's Power BI guidance lists exactly these costs for a snowflaked dimension: more tables to load and longer filter propagation chains, plus no hierarchy that spans columns from more than 1 table.

Snowflake schema vs star schema

The 2 models answer the same questions from the same fact table. They differ only in how dimensions are stored. A star schema keeps every dimension as 1 wide, denormalized table joined directly to the fact table. A snowflake schema splits some dimensions into normalized chains. A real model is often a mix: a flat date and customer dimension beside 1 snowflaked product or geography hierarchy is still called a snowflake schema.

The star wins on everything a reader of the data feels: fewer joins, simpler SQL, fewer tables in the BI tool, and hierarchies that can drill from category to product inside 1 table. The snowflake wins on what the maintainer of the data feels: a category rename touches 1 row instead of thousands, a level shared by several dimensions has 1 owner, and the tables mirror a normalized source. For the star schema's own design rules, see the star schema guide; the star schema vs snowflake schema comparison walks through the same retail model built both ways.

Star schema vs snowflake schema at a glance

Star schema
  • Dimension tables1 flat table each
  • Joins to top level1
  • Hierarchy value storedOn every row
  • Rename a categoryUpdate many rows
  • Storage savedNone
  • BI and analyst useSimple
  • Typical homeColumnar warehouses
Snowflake schema
  • Dimension tablesA chain per hierarchy
  • Joins to top level1 per level
  • Hierarchy value storedOnce
  • Rename a categoryUpdate 1 row
  • Storage savedNegligible
  • BI and analyst useMore tables to learn
  • Typical homeNormalized sources

When to use a snowflake schema

Snowflake a hierarchy when a level is a real entity with a life of its own, and keep it flat when it is only a label.

The level is maintained separately. A merchandising team owns the category tree and, several times a year, renames categories or moves subcategories between them. As its own table, each change is 1 row with 1 owner and a clear audit trail; flattened, each change rewrites every product row beneath it, and a Type 1 overwrite on 50,000 products is a large update for a 1 word rename.

The level is shared. A geography that runs from city to region to country serves the customer and store dimensions, and the supplier dimension as well. Held once in dim_city and referenced by all 3, it cannot drift; copied into 3 flat dimensions, it is 3 copies to keep in step.

The dimension is very large and part of it is sparse or volatile. A customer dimension with 200 million rows and 40 demographic columns that change monthly, filled for only a fraction of customers, is cheaper to maintain with those columns split into their own table. Kimball's name for the rapidly changing case is a mini-dimension, which is SCD Type 4. Its key goes on the fact table beside the customer's rather than on the customer row, which keeps it 1 join away.

The source already arrives normalized and nobody queries the raw layer directly. Keep the normalized tables where the data is maintained, and publish a flat, star-shaped dimension built from them for every reader. That pattern gives the snowflake's single copy and the star's single join at the same time, and it is how most modern teams end up with a snowflake schema at all.

Does a snowflake schema save storage?

Less than it seems, because the table it shrinks is small. Take a product dimension of 50,000 rows in 180 subcategories and 12 categories, with subcategory names averaging 20 bytes and category names 16. Flat, the 2 name columns cost 50,000 rows times 36 bytes, 1.8 MB. Snowflaked, each product keeps a 4 byte key and the 2 small tables hold every name once, 0.2 MB in all. The saving is about 1.6 MB.

The fact table beside it holds 500,000,000 sale lines of about 48 bytes each, 24 GB. Before compression the saving is 0.0066% of it. A columnar engine then dictionary-encodes the 180 distinct subcategory names in the flat column, so the real gap is smaller still.

2 bars on 1 scale: the fact_sales table at 24 GB fills the width, while the 1.6 MB that snowflaking the product hierarchy saves is a hairline, 0.0066% of fact_sales2 bars on 1 scale: the fact_sales table at 24 GB fills the width, while the 1.6 MB that snowflaking the product hierarchy saves is a hairline, 0.0066% of fact_sales

Storage is never the reason to snowflake a dimension in a columnar data warehouse, because the fact tables hold the bytes. Snowflaking was a storage argument when dimensions lived in row stores and disks were expensive; today it is a maintenance argument or nothing.

Outrigger tables: the snowflaking Kimball allows

An outrigger is a dimension joined to another dimension rather than to the fact table. It is a single, limited normalization, not a whole hierarchy split into levels. The classic case is a date: an employee dimension has a hire date, and analysts want hires by fiscal quarter. Instead of copying 30 calendar columns into dim_employee, the hire date becomes a key into the date dimension, relabelled with columns such as Hire Date Fiscal Year.

Margy Ross's Kimball Group Design Tip 105 says outriggers are acceptable in moderation but should be the exception rather than the rule. The Kimball technique entry adds the alternative to consider first: when 2 dimensions are correlated, carry both as separate foreign keys on the fact table, and let the fact table relate them. A bank account's open date can be an outrigger; a customer's current segment usually belongs on the fact row, where it records the segment at the time of each event.

The same sources tell you to avoid full snowflakes. The Kimball technique entry gives 2 reasons: business users find them hard to understand and navigate, and they can hurt query performance. An interviewer who hears you call a single date outrigger a snowflake schema will ask which of the 2 you mean.

Flattening a snowflaked dimension into a star dimension

/* The snowflaked tables stay the place where the hierarchy is maintained.
   Analysts and BI tools read this flat, star-shaped dimension instead. */
CREATE VIEW dim_product_flat AS
SELECT
  p.product_key,
  p.product_name,
  s.subcategory_name,
  c.category_name
FROM dim_product      AS p
JOIN dim_subcategory  AS s ON s.subcategory_key = p.subcategory_key
JOIN dim_category     AS c ON c.category_key    = s.category_key;

/* Sales by category now needs 1 join, as it would in a star schema. */
SELECT d.category_name, SUM(f.net_amount) AS revenue
FROM fact_sales       AS f
JOIN dim_product_flat AS d ON d.product_key = f.product_key
GROUP BY d.category_name;

The view keeps 1 copy of each category and subcategory name in the normalized tables and gives every query a single join to reach them.

How modern warehouses treat snowflaked dimensions

Columnar cloud warehouses changed the arithmetic in favour of the star. Google's BigQuery documentation recommends denormalizing with nested and repeated fields for performance and notes that a star schema is already optimized for analytics, so flattening it further may not change much. Microsoft's Power BI guidance says that the benefits of a single model table generally outweigh those of several, and recommends folding a snowflaked product dimension, with its subcategory and category tables, into 1 model table.

The optimizer can also remove some of the cost of a normalized design. Snowflake the database performs join elimination: when a query does not use any column of a joined table, it can drop the join, but only when the primary or unique keys and the foreign keys involved are declared with the RELY property, and it trusts you to keep those constraints true. A flattening view over a snowflake then costs nothing for queries that never read the category, as long as the keys are declared and correct.

Keep hierarchies normalized in the staging or intermediate layer, where 1 row per category is the easiest thing to keep correct, and publish flat dimensions in the layer that dashboards and analysts read. In a dbt project that is an intermediate model per level and 1 dimension model that joins them.

Should this dimension be snowflaked? A checklist

  • Snowflake it when the level has its own owner and change schedule, plus attributes of its own
  • Snowflake it when the same level is shared by 2 or more dimensions and must never drift between them
  • Snowflake it when the source is normalized and a flat view will sit between it and every reader
  • Keep it flat when the only argument is storage, since the fact tables hold the bytes
  • Keep it flat when analysts or a BI tool query the tables directly
  • Keep it flat when the level is a label with no attributes of its own, such as a category name alone
  • Use an outrigger instead when 1 dimension needs another's attributes, such as a date

Snowflake schemas and slowly changing dimensions

History is where a snowflake gets harder, and it is the point interviewers probe most. Suppose dim_product keeps Type 2 history and so does dim_subcategory. When a subcategory moves to a new category, it gets a new row with a new subcategory_key. Every product row still points to the old key, so to show the move in product history, each of those products needs a new Type 2 version pointing at the new key. 1 change in the category tree fans out into as many new product rows as the subcategory holds.

To stop the fan-out, point the product at the subcategory's durable business key instead of its versioned key, and resolve the version at query time by date, which keeps the tables independent at the cost of a range join. Or treat the upper levels as Type 1 and let history live only at the product level. Or flatten the hierarchy into dim_product and let 1 Type 2 process version the whole row, which is what a star schema does anyway. The slowly changing dimensions guide covers the Type 2 mechanics each of these relies on.

Snowflake schema vs a schema in the Snowflake database

The 2 share a word and nothing else. A snowflake schema is a way to arrange fact and dimension tables. In Snowflake the cloud data platform, a schema is a namespace: the documentation defines it as a logical grouping of database objects such as tables and views, each schema belonging to a single database, so a table's full name reads database.schema.table.

A Snowflake database schema can hold a star or snowflake schema just as easily as a data vault or 1 wide table. Searches for a Snowflake data model or a Snowflake database schema usually mean the dimensional design, and the design decision is the same on any columnar warehouse: flat dimensions by default, normalized levels where a hierarchy is maintained on its own.

How the snowflake schema comes up in data modeling interviews

Interviewers rarely ask for a definition. They ask for a model, say for an online retailer, and watch what you do with the category tree and the geography. A strong answer draws a star, names the grain of the fact table, and snowflakes only the hierarchy with a real owner, saying why in 1 sentence: the category tree is maintained by another team and changes monthly, so it gets its own table, and a flat view serves the dashboards.

The follow-ups come from the trade-offs on this page: how many joins revenue by category takes, what a category rename costs in each design, how Type 2 history behaves across the levels, and whether storage justifies the split. The questions in the data modeling interview questions and the star schema interview questions are the ones asked in real data engineering interviews. To practise drawing the model itself, the data modeling practice problems run on the same canvas as the retail example, and the data modeling round guide covers how the round runs and what it asks for.

Snowflake schema FAQ

What is a snowflake schema?+
A snowflake schema is a data warehouse model with a fact table at the centre whose dimensions are normalized into chains of tables. A product dimension, for instance, splits so that dim_product carries the key of dim_subcategory and dim_subcategory carries the key of dim_category, instead of 1 flat table that repeats the subcategory and category names on every product row. The diagram of those branching chains looks like a snowflake, which gives the model its name.
How does a snowflake schema differ from a star schema?+
Both have the same fact table. In a star schema every dimension is 1 flat table joined directly to the fact table, so any attribute is 1 join away. In a snowflake schema some dimensions are split into several tables, so attributes at the top of a hierarchy are 2 or 3 joins away. The snowflake stores each hierarchy value once; the star repeats it on every row but is simpler to query.
When would you choose a snowflake schema over a star schema?+
When a level of a hierarchy is a real entity maintained on its own schedule or by another team, when the same level is shared by several dimensions, when a dimension is very large and a group of its attributes is sparse or changes far more often than the rest, or when the source already arrives normalized and a view can present it flat. For most dimensions in a columnar warehouse, the star is the better default.
Why do most modern warehouses prefer star over snowflake?+
Columnar storage compresses repeated values well, so the space snowflaking saves is tiny: about 1.6 MB for a 50,000 row product dimension beside a 24 GB fact table. The extra joins, on the other hand, are paid by every query and every analyst who has to find the right table. Kimball, Microsoft's Power BI guidance and Google's BigQuery guidance all lean toward flat dimensions.
What is an outrigger table in a snowflake schema?+
An outrigger is a dimension joined to another dimension rather than to the fact table, such as a date dimension referenced by the hire date of an employee dimension. It is a single, limited normalization, where a snowflake normalizes whole hierarchies. Kimball treats outriggers as acceptable in moderation and full snowflaking as something to avoid.
Is a snowflake schema ever the right answer in an interview?+
Yes, for a specific hierarchy with a reason attached. A category tree that another team owns and changes is one case, and a geography that the customer dimension shares with stores and suppliers is another. So is a source that already arrives normalized behind a flat view. Interviewers look for the justification: name the level you normalize and say what it buys against the joins it adds, then keep every other dimension flat.
Is a snowflake schema normalized?+
Its dimensions are, at least partly: each hierarchy level moves to its own table so that its attributes are stored once, which is the step toward third normal form. The fact table is the same as in a star schema. A snowflake schema is still a dimensional model with facts and dimensions, not a fully normalized operational model.
Do you need a snowflake schema to use the Snowflake data warehouse?+
No. Snowflake the product is a cloud data platform, and its schemas are namespaces that group tables and views inside a database. Star and snowflake schemas run on it, and so do data vault models and wide flat tables. Sharing the name does not make the snowflake schema the recommended design on Snowflake.
02 / Why practice

The candidate who gets the offer

  1. 01

    Reading a solution is not the same as writing one

    Every engineer who has frozen on a query they had read a dozen times knows the gap. The only preparation that closes it is producing the answer yourself, under time, before the interview does it for you

  2. 02

    76% of hiring managers reject on the coding task, not the resume

    From HackerRank's 2024 Developer Skills Report. Candidates who look strong on paper still fail the live screen if they haven't done timed, executable practice

  3. 03

    The round is won on tradeoffs, not on the diagram

    Grain, star vs snowflake, SCD type, conformed dimensions, late-arriving data. Modeling under live pushback is what separates the bands, and it is the half almost nobody rehearses

Related guides