Modeling Time-Series Data

1. Designing Time-Series Schemas

ColumnPurpose
time TIMESTAMPTZSample time (always UTC)
entity_idSeries identifier (device, metric)
tags (jsonb / cols)Low-cardinality dimensions
value (numeric)Measurement
PK(entity_id, time) — note order for clustering

2. Partitioning by Time

GranularityUse
DailyHigh-volume metrics
WeeklyMid-volume
MonthlyLower-volume series
ToolsTimescaleDB hypertables, pg_partman, native PG RANGE
BenefitCheap retention via DROP PARTITION

3. Implementing Downsampling Strategies

ApproachDetail
Continuous aggregates (Timescale)Auto-materialized rollups
time_bucket('1 hour', ts)Bucket function
Rollup tablesPer-bucket avg/min/max/count
Multi-tier1s → 1m → 1h → 1d retention pipeline
LTTB algorithmVisual downsampling preserving shape

4. Designing Data Retention Policies

TierRetentionResolution
Hot7 daysRaw
Warm30 days1-minute
Cool1 year1-hour
Cold5+ years1-day

5. Indexing Time-Based Queries

IndexUse
(entity_id, time DESC)Latest per entity
BRIN on timeTiny size on append-only data
Per-partition local indexesSmall + cache-friendly
Covering INCLUDE(value)Index-only scans

6. Handling Out-of-Order Data

ChallengeMitigation
Late arrivalsAllow back-dated writes; recompute rollups
WatermarksProcess windows once events past watermark
Idempotent UPSERTTolerate duplicate writes
CompactionMerge late points into bucket aggregates

7. Implementing Compression Strategies

MethodDetail
Delta + Gorilla (Facebook)Float compression for metrics
TimescaleDB compression5–20× on column segments
Columnar storageClickHouse, Parquet
Run-length encodingFor repeating values

8. Designing Rollup Tables

PatternDetail
Time bucket + dimensionsPK: (bucket_ts, entity_id, dim...)
Pre-computed aggssum, count, min, max, sum_of_squares
Re-aggregationHigher-tier rollups built from lower-tier
BackfillReplay historical raw to rebuild

9. Managing Hot and Cold Data Storage

StrategyDetail
Tiered tablesDetach old partition → cold storage
S3 + foreign data wrapperQuery cold as external table
Columnar archiveParquet on S3 + Athena/Trino
Auto-policyTimescaleDB add_retention_policy

10. Optimizing Time-Series Query Patterns

PatternOptimization
Latest point per entitySELECT DISTINCT ON (entity_id) ... ORDER BY time DESC
Range scanWHERE time BETWEEN ... + partition pruning
AggregationQuery rollup tier matching granularity
Gap-fillgenerate_series + LEFT JOIN
Last-observation-carried-forwardLAG / window functions