· InfluxDB· TimescaleDB· PostgreSQL· IoT· tidsserier· database· wM-Bus· sammenligning
InfluxDB vs TimescaleDB til IoT tidsseriedata — sammenligning 2025
InfluxDB vs TimescaleDB til IoT tidsseriedata: query-sprog, komprimering, SQL-kompatibilitet, skalering, pris og brug i wM-Bus gateway-platforme.
Af M-Bus Gateway
Valget mellem InfluxDB og TimescaleDB er afgørende for IoT-platformers datalagring. Her er den tekniske sammenligning med fokus på wM-Bus gateway-use cases.
Kerneforskel
InfluxDB 3.0:
→ Specialiseret tidsserie-database (ikke relationel)
→ InfluxQL / Flux query-sprog (proprietært)
→ Høj indlæsningshastighed — optimeret til sensor-streams
→ Cloud-first: InfluxDB Cloud Serverless
→ Ingen SQL — integration med eksisterende ORM'er er kompleks
TimescaleDB:
→ PostgreSQL extension — 100% SQL-kompatibel
→ Hypertables partitionerer automatisk på tid
→ Eksisterende PostgreSQL-tooling virker direkte
→ Kontinuerte aggregater: forudberegnede rollup-tabeller
→ Seamless join mod relationelle data (ejendomme, lejligheder)
Query-sprog sammenligning
-- TimescaleDB: Standard SQL
-- Gennemsnitlig HCA pr. lejlighed over seneste 7 dage
SELECT
mi.unit_id,
time_bucket('1 day', r.timestamp) AS day,
AVG(r.value) AS avg_hca
FROM readings r
JOIN meter_installations mi ON r.meter_installation_id = mi.id
WHERE r.timestamp > NOW() - INTERVAL '7 days'
AND mi.tenant_id = $1
GROUP BY mi.unit_id, day
ORDER BY day DESC;
// InfluxDB Flux — tilsvarende query
// Ingen join-mulighed mod relationelle data
from(bucket: "readings")
|> range(start: -7d)
|> filter(fn: (r) => r["_measurement"] == "hca")
|> filter(fn: (r) => r["tenant_id"] == "550e8400...")
|> aggregateWindow(every: 1d, fn: mean, createEmpty: false)
|> yield(name: "mean")
Komprimering
TimescaleDB:
Komprimering (column-store):
Standard PostgreSQL row: ~200 bytes/aflæsning
Komprimeret: ~15 bytes/aflæsning (93% reduktion)
Aktivering: SELECT compress_chunk(chunk) for chunks > 7 dage
Policy (automatisk):
SELECT add_compression_policy('readings', INTERVAL '7 days');
InfluxDB 3.0:
Apache Parquet column-format: typisk 85-95% komprimering
Automatisk — ingen konfiguration nødvendig
Vinder: Tilnærmelsesvis ens komprimering i praksis
Skalering og indlæsningshastighed
Benchmark (wM-Bus use case):
Ejendom med 100 lejligheder × 3 HCA pr. lejlighed = 300 målere
Daglig indlæsning: 300 readings/dag
10.000 ejendomme: 3.000.000 readings/dag
TimescaleDB (Hetzner CX32, 4 vCPU / 8GB):
Indlæsning: 50.000 rows/sek via COPY — 3M/dag på 60 sek
Query (7-dages aggregat): under 200ms med komprimering
Disk: ~15GB efter 10 år (3M/dag × 365 × 10 × 15 bytes)
InfluxDB Cloud Serverless:
Indlæsning: ubegrænset (serverless)
Query: sammenlignelig ved enkle aggregater
Pris: ~$0.004/MB indlæst + $0.01/GB lagret
10 år disk-pris: ~$1.500/år (vs. ~$0 for TimescaleDB på eksisterende Hetzner)
Join med relationelle data
-- TimescaleDB: Direkte join er afgørende for afregning
-- Pro-rata beregning kræver:
-- reading.timestamp → meter_installation.unit_id → occupancy.start/end_date → lejer
SELECT
o.tenant_name,
o.start_date,
o.end_date,
SUM(r.value) AS total_hca
FROM readings r
JOIN meter_installations mi ON r.meter_installation_id = mi.id
JOIN units u ON mi.unit_id = u.id
JOIN occupancies o ON u.id = o.unit_id
AND r.timestamp BETWEEN o.start_date AND COALESCE(o.end_date, NOW())
WHERE u.property_id = $1
AND r.timestamp BETWEEN $2 AND $3
GROUP BY o.id, o.tenant_name, o.start_date, o.end_date;
InfluxDB: Ingen native join mod PostgreSQL
→ Kræver application-level join (to separate queries + Python merge)
→ Fejlbehæftet og langsommere end TimescaleDB's single query
Vinder: TimescaleDB (klar) — relationelle joins er kritiske for afregning
Kontinuerte aggregater
-- TimescaleDB: Forudberegnede månedlige aggregater
CREATE MATERIALIZED VIEW monthly_readings
WITH (timescaledb.continuous) AS
SELECT
time_bucket('1 month', timestamp) AS month,
meter_installation_id,
AVG(value) AS avg_value,
MAX(value) AS max_value,
MIN(value) AS min_value,
COUNT(*) AS reading_count
FROM readings
GROUP BY month, meter_installation_id;
-- Opdater automatisk:
SELECT add_continuous_aggregate_policy(
'monthly_readings',
start_offset => INTERVAL '3 months',
end_offset => INTERVAL '1 hour',
schedule_interval => INTERVAL '1 day'
);
-- Dashboard-query bruger aggregat (under 10ms):
SELECT month, avg_value FROM monthly_readings
WHERE meter_installation_id = $1
ORDER BY month DESC LIMIT 24;
Beslutningsguide
Brug TimescaleDB hvis:
✅ Du allerede bruger PostgreSQL (samme stack)
✅ Du har komplekse joins mod relationelle data
✅ Du vil bruge eksisterende ORM (SQLAlchemy/SQLModel)
✅ Du kører on-premise eller på en VPS
✅ SQL-kompetence i teamet
✅ GDPR kræver EU-hosting med fuld kontrol
Brug InfluxDB hvis:
✅ Ren sensor-stream uden relationelle joins
✅ Serverless-model foretrækkes
✅ Ekstrem skala (milliarder af datapunkter/dag)
✅ Team kender Flux/InfluxQL i forvejen
✅ Grafana som primær visualisering (InfluxDB er native Grafana-kilde)
M-Bus Gateway valg: TimescaleDB
Årsag: Pro-rata afregning kræver joins mod occupancy-tabel.
Hetzner hosting → ingen ekstra cloud-abonnement.
SQLModel ORM virker direkte — ingen Flux-kompetence nødvendig.
Migration: InfluxDB til TimescaleDB
# Migrationscript: InfluxDB → TimescaleDB
from influxdb_client import InfluxDBClient
import asyncpg
async def migrate_readings(
influx_url: str,
influx_token: str,
pg_dsn: str,
) -> None:
influx = InfluxDBClient(url=influx_url, token=influx_token, org="myorg")
pg = await asyncpg.connect(pg_dsn)
query_api = influx.query_api()
tables = query_api.query("""
from(bucket: "readings")
|> range(start: 2020-01-01T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "hca")
""")
rows = []
for table in tables:
for record in table.records:
rows.append((
record.get_time(),
record["meter_id"],
record.get_value(),
))
# Bulk insert via COPY
await pg.copy_records_to_table(
"readings_migration",
records=rows,
columns=["timestamp", "meter_id", "value"],
)
await pg.close()
Konklusion
TimescaleDB er det rigtige valg for wM-Bus platforme der kræver joins mod relationelle data til afregning og pro-rata beregning. InfluxDB er overlegen ved ren sensor-streaming uden relationsdata. TimescaleDB's 93% komprimering og kontinuerte aggregater giver InfluxDB-lignende performance med fuld SQL-kompatibilitet.
Se TimescaleDB hypertable guide eller TimescaleDB aggregater guide.