Dimensional Modeling β A Beginner's Guide
What is Dimensional Modeling?
Dimensional modeling is a way to organize data in a data warehouse so that itβs easy to understand and fast to query. It was popularized by Ralph Kimball in the 1990s and is still widely used today.
The Core Idea
Instead of storing data in complex, normalized tables (like in a regular database), we organize it around business processes using two types of tables:
Date"] D2["π¦ What?
Product"] D3["π€ Who?
Customer"] D4["πͺ Where?
Store"] end subgraph fact["Fact Table (The Measurements)"] F["π° Sales
β’ quantity
β’ revenue
β’ cost"] end D1 --> F D2 --> F D3 --> F D4 --> F style F fill:#dbeafe,stroke:#2563eb style D1 fill:#d1fae5,stroke:#059669 style D2 fill:#d1fae5,stroke:#059669 style D3 fill:#d1fae5,stroke:#059669 style D4 fill:#d1fae5,stroke:#059669
Real-World Analogy
Think of a receipt from a store:
- Fact = The numbers on the receipt (quantity, price, total)
- Dimensions = The context (what store, what date, what product, which customer)
Fact Tables: The Numbers
What is a Fact Table?
A fact table stores the measurements of a business process β things you can count, sum, or average.
(FK)"] F2["product_key
(FK)"] F3["customer_key
(FK)"] F4["store_key
(FK)"] F5["quantity_sold
(measure)"] F6["revenue
(measure)"] F7["discount
(measure)"] end style F1 fill:#fef3c7,stroke:#d97706 style F2 fill:#fef3c7,stroke:#d97706 style F3 fill:#fef3c7,stroke:#d97706 style F4 fill:#fef3c7,stroke:#d97706 style F5 fill:#dbeafe,stroke:#2563eb style F6 fill:#dbeafe,stroke:#2563eb style F7 fill:#dbeafe,stroke:#2563eb
Types of Facts
| Type | Description | Example |
|---|---|---|
| Additive | Can be summed across all dimensions | Revenue, Quantity |
| Semi-Additive | Can be summed across some dimensions | Account Balance (canβt sum across time) |
| Non-Additive | Cannot be summed | Ratios, Percentages |
Example Fact Table
| date_key | product_key | customer_key | store_key | quantity | revenue | cost |
|---|---|---|---|---|---|---|
| 20240115 | 1001 | 5001 | 10 | 2 | 59.98 | 30.00 |
| 20240115 | 1002 | 5002 | 10 | 1 | 149.99 | 80.00 |
| 20240116 | 1001 | 5001 | 11 | 3 | 89.97 | 45.00 |
Dimension Tables: The Context
What is a Dimension Table?
A dimension table provides the descriptive context for the facts β the who, what, when, and where.
Common Dimensions
| Dimension | Answers | Example Attributes |
|---|---|---|
| Date | When? | Year, Quarter, Month, Day, Is_Weekend |
| Product | What? | Name, Category, Brand, Price |
| Customer | Who? | Name, Segment, Location, Loyalty_Level |
| Store/Location | Where? | Address, City, Region, Manager |
| Employee | By whom? | Name, Department, Hire_Date |
Example Dimension Table: Product
| product_key | product_name | category | brand | unit_price | is_active |
|---|---|---|---|---|---|
| 1001 | Wireless Mouse | Electronics | TechBrand | 29.99 | Yes |
| 1002 | Mechanical Keyboard | Electronics | KeyMaster | 149.99 | Yes |
| 1003 | USB Hub | Accessories | TechBrand | 19.99 | No |
Star Schema: The Classic Design
What is a Star Schema?
The most common dimensional model. Itβs called a βstarβ because the diagram looks like a star β one fact table in the center, surrounded by dimension tables.
βββββββββ
date_key
full_date
day_name
month
quarter
year"] DIM_PRODUCT["π¦ dim_product
βββββββββ
product_key
product_name
category
brand
unit_price"] FACT["π° fact_sales
βββββββββ
date_key (FK)
product_key (FK)
customer_key (FK)
store_key (FK)
βββββββββ
quantity
revenue
cost"] DIM_CUSTOMER["π€ dim_customer
βββββββββ
customer_key
customer_name
segment
country"] DIM_STORE["πͺ dim_store
βββββββββ
store_key
store_name
city
state
manager"] DIM_DATE --> FACT DIM_PRODUCT --> FACT FACT --> DIM_CUSTOMER FACT --> DIM_STORE style FACT fill:#dbeafe,stroke:#2563eb style DIM_DATE fill:#d1fae5,stroke:#059669 style DIM_PRODUCT fill:#d1fae5,stroke:#059669 style DIM_CUSTOMER fill:#d1fae5,stroke:#059669 style DIM_STORE fill:#d1fae5,stroke:#059669
Why Star Schema?
| Benefit | Explanation |
|---|---|
| Simple to understand | Business users can easily read it |
| Fast queries | Fewer joins = faster performance |
| Tool-friendly | BI tools (Tableau, Power BI) love it |
| Flexible | Easy to add new dimensions |
Snowflake Schema: The Normalized Cousin
What is a Snowflake Schema?
A variation where dimension tables are normalized (split into sub-tables). It looks like a snowflake because of the branching.
product_key
product_name
category_key (FK)"] DIM_CATEGORY["π·οΈ dim_category
category_key
category_name
department_key (FK)"] DIM_DEPARTMENT["π’ dim_department
department_key
department_name"] FACT --> DIM_PRODUCT DIM_PRODUCT --> DIM_CATEGORY DIM_CATEGORY --> DIM_DEPARTMENT style FACT fill:#dbeafe,stroke:#2563eb style DIM_PRODUCT fill:#d1fae5,stroke:#059669 style DIM_CATEGORY fill:#fef3c7,stroke:#d97706 style DIM_DEPARTMENT fill:#fce7f3,stroke:#db2777
Star vs Snowflake
| Aspect | Star Schema | Snowflake Schema |
|---|---|---|
| Structure | Denormalized (flat) | Normalized (hierarchical) |
| Query Speed | β‘ Faster (fewer joins) | π’ Slower (more joins) |
| Storage | More space (duplicate data) | Less space |
| Simplicity | β Easier to understand | β More complex |
| Recommendation | β Usually preferred | Use when storage is critical |
The Date Dimension: A Special Case
Why is Date Special?
Every data warehouse needs a date dimension. Itβs pre-built with useful attributes for time-based analysis.
Example Date Dimension Table
| date_key | full_date | day_name | month | quarter | year | is_weekend | is_holiday |
|---|---|---|---|---|---|---|---|
| 20240115 | 2024-01-15 | Monday | January | Q1 | 2024 | No | No |
| 20240116 | 2024-01-16 | Tuesday | January | Q1 | 2024 | No | No |
| 20240120 | 2024-01-20 | Saturday | January | Q1 | 2024 | Yes | No |
This lets you easily query things like:
- βShow me all sales on weekendsβ
- βCompare Q1 vs Q2β
- βWhatβs the trend for Mondays?β
Slowly Changing Dimensions (SCD)
The Problem
What happens when dimension data changes? A customer moves to a new city. A product gets a new price. How do you track history?
City: New York"] end subgraph after["After Move"] A["π€ John Smith
City: Los Angeles"] end before --> |"Moves!"| after Q["β What do we do
with old sales in NY?"] style Q fill:#fef3c7,stroke:#d97706
SCD Types
Never change
(retain original)"] SCD --> T1["Type 1
Overwrite
(lose history)"] SCD --> T2["Type 2
Add new row
(keep history)"] SCD --> T3["Type 3
Add new column
(limited history)"] style T0 fill:#f1f5f9,stroke:#64748b style T1 fill:#fecaca,stroke:#dc2626 style T2 fill:#d1fae5,stroke:#059669 style T3 fill:#fef3c7,stroke:#d97706
SCD Type 2 Example (Most Common)
| customer_key | customer_id | name | city | start_date | end_date | is_current |
|---|---|---|---|---|---|---|
| 1001 | C100 | John Smith | New York | 2020-01-01 | 2024-06-30 | No |
| 1002 | C100 | John Smith | Los Angeles | 2024-07-01 | 9999-12-31 | Yes |
Same customer, two rows! Old sales link to key 1001 (NY), new sales link to key 1002 (LA).
When to Use Each Type
| Type | Use When | Example |
|---|---|---|
| Type 0 | Value should never change | Original signup date |
| Type 1 | History doesnβt matter | Fixing typos |
| Type 2 | Need full history | Customer address, product price |
| Type 3 | Only need previous value | Previous manager |
Building a Dimensional Model: Step by Step
'What are we measuring?'"] S2["2οΈβ£ Declare the Grain
'What does one row represent?'"] S3["3οΈβ£ Identify Dimensions
'What context do we need?'"] S4["4οΈβ£ Identify Facts
'What numbers do we measure?'"] S1 --> S2 --> S3 --> S4 style S1 fill:#dbeafe,stroke:#2563eb style S2 fill:#d1fae5,stroke:#059669 style S3 fill:#fef3c7,stroke:#d97706 style S4 fill:#fce7f3,stroke:#db2777
Example: E-Commerce Orders
| Step | Question | Answer |
|---|---|---|
| 1. Business Process | What are we analyzing? | Online Orders |
| 2. Grain | Whatβs one row? | One order line item |
| 3. Dimensions | Whatβs the context? | Date, Customer, Product, Promotion |
| 4. Facts | What do we measure? | Quantity, Revenue, Discount, Shipping Cost |
Is Dimensional Modeling Still Relevant?
Yes! Hereβs why itβs still widely used:
| Modern Context | Why Dimensional Modeling Works |
|---|---|
| Cloud Data Warehouses (Snowflake, BigQuery, Redshift) | Still optimized for star schemas |
| BI Tools (Tableau, Power BI, Looker) | Expect dimensional models |
| Business Users | Understand star schemas intuitively |
| Performance | Denormalized data = fast queries |
Modern Adaptations
Tools like dbt now help build dimensional models using SQL transformations, making it easier than ever.
Quick Reference
Fact vs Dimension Cheat Sheet
| Question | Fact Table | Dimension Table |
|---|---|---|
| What does it store? | Measurements | Context/Descriptions |
| Example columns | Revenue, Quantity, Cost | Name, Category, Date |
| Row count | Many (millions+) | Fewer (thousands) |
| Changes often? | New rows added constantly | Changes slowly |
| Width | Narrow (few columns) | Wide (many columns) |
Key Terms
| Term | Simple Definition |
|---|---|
| Grain | What one row in a fact table represents |
| Surrogate Key | System-generated ID (1, 2, 3β¦) used as primary key |
| Natural Key | Business ID from source system (SKU, Customer ID) |
| Conformed Dimension | Same dimension used across multiple fact tables |
| Junk Dimension | Groups miscellaneous flags/indicators |
| Degenerate Dimension | Dimension stored in fact table (e.g., Order Number) |
Summary
Store measurements
(revenue, quantity)"] DM --> DIM["π¦ Dimension Tables
Store context
(who, what, when, where)"] DM --> STAR["β Star Schema
Simple, fast, popular"] DM --> SCD["π Handle Changes
SCD Type 1, 2, 3"] style DM fill:#dbeafe,stroke:#2563eb style FACT fill:#d1fae5,stroke:#059669 style DIM fill:#fef3c7,stroke:#d97706 style STAR fill:#fce7f3,stroke:#db2777 style SCD fill:#e0e7ff,stroke:#6366f1
Remember:
- Fact tables = The numbers you measure
- Dimension tables = The context around those numbers
- Star schema = Facts in the center, dimensions around it
- Keep it simple = Business users should understand it!
Inspired by Ralph Kimballβs dimensional modeling methodology. For deeper learning, check out βThe Data Warehouse Toolkitβ by Ralph Kimball.