Facts and dimensions
A fact table holds the events you measure — sales lines, transactions, tickets. Long and narrow: mostly keys and numeric values.
A dimension table holds the things you slice by — Product, Customer, Date, Store. Short and wide: one row per entity, many descriptive attributes.
A star schema is one fact table surrounded by dimensions, each joined one-to-many from the dimension to the fact.
Why not one big flat table
A flat table repeats every descriptive attribute on every row. VertiPaq compresses well, so the size penalty is smaller than you'd expect — but the real costs are elsewhere.
Relationships and filter propagation stop working the way DAX expects. Reusing a dimension across two fact tables becomes impossible. Distinct counts get expensive. And time intelligence needs a proper Date dimension, which a flat table doesn't give you.
Power BI's engine and DAX's filter model are both designed around the star. Fighting that shape costs more than it saves.
Snowflaking
A snowflake normalises dimensions further — Product joins to Subcategory joins to Category. It's tidier in database terms but adds hops that slow filter propagation and complicate DAX.
In Power BI, flatten snowflaked dimensions into a single wide dimension in Power Query. Merge Category and Subcategory into the Product table and be done.
The Date dimension
Every model needs a dedicated, contiguous Date table marked with Mark as Date Table. Without one, time intelligence functions like TOTALYTD and SAMEPERIODLASTYEAR misbehave or silently return wrong results.
Build it in Power Query, or with DAX CALENDAR/CALENDARAUTO. It must contain one row per day with no gaps, covering the full range of your facts — including the whole of the final year, or year-to-date calculations break at the edges.