Understanding Slowly Changing Dimensions
In data warehousing, different strategies exist for handling data that changes over time:- Type 0 (Retain Original): The dimension never changes once created
- Type 1 (Overwrite): Updates replace the original values with no history kept
- Type 2 (Add New Row): Preserves history by creating new records when changes occur
- Type 3 (Add New Attribute): Maintains limited history by adding columns for previous values
- Customer status changes
- Product pricing and categorization
- Order processing states
- Employee roles and departments
Basic Configuration
PrerequisitesBefore setting up snapshots:
- Create a target schema for snapshots in your data warehouse
- Ensure source data has either reliable timestamps or columns to track for changes
- Set up the
snapshots/directory in your dbt project
.sql files within your project’s snapshots directory:
Snapshot Strategies
dbt offers two primary strategies to detect changes in your data:- Timestamp Strategy
- Check Strategy
Uses a timestamp column to detect changes. This is the best choice when your source data reliably updates a timestamp column when records change.When to use:The updated_at parameter specifies which column contains the last-updated timestamp.
- Source data has a reliable updated_at column
- Need to track when changes occurred
- Want to capture all changes based on timing
How Snapshots Work Behind the Scenes
When you rundbt snapshot, dbt:
- Creates the snapshot table if it doesn’t exist
- For existing tables, determines which records have changed based on your strategy
- Marks previously current records that changed as no longer current (
dbt_valid_togets timestamp) - Inserts new versions of changed records as current (with
dbt_valid_toas null) - Inserts completely new records
Metadata Fields
As of dbt version ≥ 1.9, snapshots add four tracking columns:dbt_valid_from: When this version became validdbt_valid_to: When this version became invalid (null for current version)dbt_updated_at: Timestamp when the snapshot was takendbt_scd_id: Unique identifier for each version
- Identify current records (
dbt_valid_to IS NULL) - Find records valid at a specific point in time
- Determine when changes occurred
- Track the duration a particular version was active
Step-by-Step Example
Let’s implement a simple snapshot to track customer status changes: 1. Create a staging model for the source dataAdvanced Configuration
Invalidating Hard Deletes By default, snapshots don’t track when records are deleted from the source. To track deletions:invalidate_hard_deletes=true, dbt will:
- Identify records in the snapshot that no longer exist in the source
- Set their
dbt_valid_totimestamps to mark them as no longer current
Best Practices for Snapshots
1. Snapshot Frequency- Schedule snapshots based on how frequently your source data changes and how important it is to capture every change
- For critical data, run snapshots before dependent models to ensure they use the latest history
- Consider storage costs versus historical data needs
- Use a dedicated schema for snapshots to make maintenance easier
- Apply appropriate indexes to snapshot tables for faster querying
- Consider partitioning large snapshot tables by date
- For very large tables, use incremental snapshots with time-based filters
- Infrequent snapshots: Running snapshots too infrequently might miss intermediate state changes
- Missing source filter: Always filter your source query to include only necessary data
- Unreliable timestamps: Ensure your
updated_atfield actually updates when records change - Using snapshots for high-frequency changes: Consider incremental models for data that changes very frequently