Latticework

Command Palette

Search for a command to run...

Data Modeling

Star & Snowflake Schema

18 min

Explanation

A star schema is the standard shape for analytics/data-warehouse tables: one central fact table (every row is a measurable event — "this sale happened, for this amount, at this time"), surrounded by dimension tables it references via foreign keys (customer, product, date, store — the "who/what/when/where" you'd filter or group by).

def is_valid_star_schema(fact_fks, dimension_tables):
    return set(fact_fks).issubset(set(dimension_tables))

fact_sales_fks = ["customer", "product", "date"]
dimensions = ["customer", "product", "date", "store"]
print(is_valid_star_schema(fact_sales_fks, dimensions))   # True

A snowflake schema is the same idea, but with dimension tables further normalized (e.g. product splitting off into its own category and department tables) — more normalized, less redundant, but requires more joins to query.

Try it

Star schemas favor query SIMPLICITY (fewer joins, faster analytics queries) at the cost of some redundancy; snowflake schemas favor normalization (less redundancy, smaller storage) at the cost of needing more joins -- exactly the same time/space-flavored tradeoff from the Complexity Analysis course, applied to schema design.

Loading editor…
Explanation

Every foreign key in the fact table should point to a REAL row in its dimension — a fact row referencing a product_id that doesn't exist in the products dimension is an orphaned row, usually a sign of a broken ETL pipeline (a product got deleted from the dimension, but historical fact rows still reference it):

def find_orphaned_fact_rows(fact_rows, dimension_keys):
    orphans = []
    for i, row in enumerate(fact_rows):
        for dim, valid_keys in dimension_keys.items():
            if row.get(dim) not in valid_keys:
                orphans.append((i, dim))
    return orphans

Real data warehouses run exactly this kind of check as part of their data-quality pipeline — catching orphaned fact rows before they corrupt a dashboard or report downstream.

Exercise

Write `is_valid_star_schema(fact_fks, dimension_tables)`: return True if every foreign key in `fact_fks` has a matching entry in `dimension_tables` (i.e. `fact_fks` is a subset of `dimension_tables`).

Exercise

Write `find_orphaned_fact_rows(fact_rows, dimension_keys)`: `dimension_keys` maps each dimension column name to the set of valid keys in that dimension. Return a list of `(row_index, dimension)` pairs for every fact row whose foreign key doesn't exist in its dimension.

Quiz

In a star schema, what's the key structural difference between the fact table and the dimension tables?

Checkpoint

You understand the fact/dimension split in a star schema, the star-vs-snowflake tradeoff, and can check fact rows for referential integrity against their dimensions.