Star Schema vs Snowflake Schema
Star and snowflake schemas are the two dominant shapes for analytics data. This guide explains fact and dimension tables, how the two differ, and how to choose between them.
Analytical databases are shaped differently from the transactional ones most application developers know. Where an operational schema is normalized to prevent update anomalies, a data warehouse is optimized for a different job: answering aggregate questions over huge volumes of history, fast. That different goal produces different shapes, and the two dominant ones are the star schema and the snowflake schema. Both organize data into facts and dimensions; they differ in how far they normalize the dimensions, and that single difference drives all their trade-offs.
This guide explains the fact-and-dimension model both schemas share, then contrasts the two and gives guidance on choosing. If you have only ever modeled transactional databases, this is a useful expansion of your toolkit, because the rules you learned there, normalize aggressively, partly invert here. You can model both shapes in the editor at /diagrams or the ERD tooling at /diagram-tools/erd-tool, where the characteristic star and snowflake layouts become literally visible.
Facts and dimensions: the shared foundation
Both schemas divide the world into fact tables and dimension tables. A fact table holds the measurements, the numeric events you want to analyze: a sale, with its amount, quantity, and discount. Fact tables are typically long and narrow, with one row per event and many millions of rows, and they hold mostly numbers plus foreign keys. A dimension table holds the descriptive context by which you slice those measurements: the product sold, the store it sold in, the date, the customer.
The classic query pattern is aggregating a fact measure grouped by dimension attributes: total sales amount by product category by month by region. The fact table provides the amount, and the dimension tables provide the category, month, and region to group by. This fact-and-dimension separation is called dimensional modeling, and it is the shared foundation of both star and snowflake schemas. What distinguishes them is purely how the dimension tables themselves are structured.
The star schema: denormalized dimensions
In a star schema, each dimension is a single flat table, denormalized so that all its descriptive attributes live together. A Product dimension holds the product name, category, subcategory, brand, and supplier all in one table, even though category and brand repeat across many products. The fact table sits in the center with foreign keys radiating out to each dimension table, and the resulting diagram looks like a star, which is where the name comes from.
The star schema's virtue is query simplicity and speed. Answering "sales by category" requires joining the fact table to just one dimension table, because category lives right there in the flat Product dimension. Fewer joins means faster queries and simpler SQL, which is exactly what analysts and reporting tools want. The cost is redundancy: the category name is stored on every product row, consuming more space and creating the same update anomalies normalization exists to prevent. In a warehouse, though, that trade is usually worth it, because data is loaded in controlled batches rather than updated constantly, so the anomalies rarely bite.
The snowflake schema: normalized dimensions
A snowflake schema takes those flat dimensions and normalizes them, splitting each into multiple related tables. The Product dimension no longer holds the category name directly; instead it holds a category_id pointing at a separate Category dimension table, which might itself point at a Department table. The dimensions branch out into further tables, and the diagram takes on the many-armed look of a snowflake, hence the name.
The snowflake's advantage is reduced redundancy and storage: the category name is stored once in the Category table rather than repeated on every product. It also makes dimension hierarchies explicit and can ease maintenance when descriptive data changes. The cost is more joins. Answering "sales by category" now requires joining the fact table to Product and then to Category, and deeper hierarchies mean deeper join chains, which are slower and produce more complex SQL. The snowflake trades query performance and simplicity for storage efficiency and normalization, the reverse of the star's bargain.
Choosing between them
The decision comes down to what you are optimizing for, and in most modern warehouses the star schema wins by default. Storage is cheap, query performance and analyst productivity are valuable, and columnar warehouse engines compress the redundancy in flat dimensions efficiently, blunting the star's main drawback. Unless you have a specific reason to snowflake, start with a star.
- Star schema: fewer joins, faster queries, simpler SQL; more storage and redundancy. The usual default.
- Snowflake schema: less redundancy and storage, explicit hierarchies; more joins and slower, more complex queries.
- Favor a star when query performance and analyst simplicity matter most, which is most of the time.
- Favor a snowflake for very large dimensions where storage savings are significant, or when hierarchies must be explicit.
- Modern columnar warehouse engines reduce the storage penalty of star schemas, strengthening the default choice.
- You can mix approaches: keep most dimensions flat and snowflake only the few that genuinely benefit.
- Neither is a normalized transactional schema; both deliberately trade normalization for analytical query performance.