Time-Series Storage for Sensor Data — A Benchmark
The methodology behind our comparison of four time-series databases (ClickHouse, TimescaleDB, InfluxDB, QuestDB) on a hardware-sensor workload. Use it to reproduce the numbers or to evaluate your own store.
The workload
1,000,000 rows across 1,000 simulated devices, each emitting 1,000 timestamps of temperature (float, slow random walk around 22°C). Schema: (timestamp, source_id, metric, value). 5,000-row batches.
The harness
A small Python runner drives each database through a common driver interface — connect, setup, ingest, run_query, storage_bytes — and measures three things: ingest throughput, query latency on five patterns, and on-disk storage. Each database runs one at a time (via Docker Compose) to avoid memory contention.
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
docker compose up -d clickhouse
python bench.py --db clickhouse --out results/clickhouse.json
docker compose down -vRepeat for timescaledb and influxdb.
The queries
| Key | Shape |
|---|---|
Q1_window | one device’s last 5 minutes |
Q2_distinct_metrics | distinct metric names for one device |
Q3_fleet_avg | mean across all devices, last 1 minute |
Q4_count_range | count of points in last 10 minutes |
Q5_last_n | last 10 readings for one device |
Tuning knobs
| Where | Constant | Meaning |
|---|---|---|
generate.py | NUM_DEVICES, TICKS_PER_DEVICE | total rows = product |
bench.py | --runs | how many times each query runs (default 5) |
drivers/*.py | BATCH_SIZE | rows per batch (default 5000) |
Notes
- QuestDB hit reproducible writer-pool contention under this setup (
table busy, ILP broken pipe), so it has no publishable numbers here. - Published numbers were on an M3 MacBook Pro (8 cores, Docker Desktop, 4 GiB), single-DB-at-a-time. Expect ±10% on similar hardware; larger deviations usually mean a different tunable (compression, indices, batch size).
Last updated on