Wide, hybrid or narrow tables?
| Dimension | Wide tables | Hybrid (medium) tables | Narrow tables |
|---|---|---|---|
| In one line | One row per entity and moment, one column per metric | A metric-name column plus one value column per data type | One row per entity, moment and metric |
| Shape | (time, host, cpu, mem, disk) | (time, host, metric, value_float, value_int, value_text) | (time, host, metric, value) |
| Adding a metric | ALTER TABLE ... ADD COLUMN, and every query and ingest job that lists columns | Insert rows with the new name; only a new data type adds a column | Insert rows with the new name |
| Rows for one reading of six metrics | 1 | 6 | 6 |
| Value types | Each metric has its own native type | Native types, but something must map each metric to its column | One type (often a double); otherwise a table per type, or JSONB and casts |
| Reading many metrics together | One row, no joins | Filter on metric, pivot, and CASE across types | A pivot, or a join per metric |
| Sparse data | NULL cells when values arrive apart; cheap in columnar storage | NULLs in the unused type columns | No NULLs: a missing value is a missing row |
| Compression (TigerData’s rating) | Good: NULL-heavy columns compress well | Good: uniform typed columns | Excellent: uniform columns |
| Reach for it when | Metrics are known, stable and read together | Metrics come and go but fall into a few types, or differ per tenant | Metrics come and go and are read one series at a time |
| Where you see it | Host and sensor tables; InfluxDB points with several fields; ArcticDB frames with very many columns | TigerData’s medium layout; fixed columns plus jsonb or a ClickHouse Map | Prometheus series; OpenTelemetry metrics in ClickHouse; pandas melt() output |
Rule of thumb
Start from how you read, not how data arrives. If dashboards show many metrics of one thing at one moment and the list is stable, go wide. If metrics come and go and are read one series at a time, go narrow. If they come and go but you want native types, add typed value columns. Mixing is normal: TigerData suggests a wide table for core metrics and a medium table for custom ones. Moving between layouts later means rewriting history, so when unsure, pick the one that extends without migrations.
Sources
- TigerData docs: Wide, narrow, and medium tables (comparison table, combining layouts)
- Chris Engelbert and Carlota Soto, Timescale: Designing your database schema, wide vs. narrow Postgres tables (Mar 2024)
- PostgreSQL docs: ALTER TABLE (ADD COLUMN)
- Prometheus docs: Data model
- OpenTelemetry Collector Contrib: ClickHouse exporter gauge table definition
- InfluxDB docs: Line protocol (field set)
- ArcticDB README (data big in row count and column count)
- pandas user guide: Reshaping and pivot tables (melt)
- PostgreSQL docs: JSON types