Introduzione e contesto
Sto refactoring un sistema che memorizza i dati energetici (consumo di gas / elettricità, consegna di energia elettrica). I dati provengono da un sensore che registra i dati assoluti ogni 15 minuti in uno schema che è soggetto a modifiche in futuro (leggi: richiede l'archiviazione dei documenti).
Situazione attuale
I dati grezzi sono memorizzati in un database MongoDB. Un processo in background legge questi dati e li converte in dati delta strutturati che sono memorizzati in un database MySQL, in diverse risoluzioni.
Schema MongoDB:
| device_id (uint) | timestamp (ISODate) | data (unspecified object) |
Schema MySQL: (più tabelle: hour
, day
, month
, year
)
| device_id (uint) | timestamp (datetime) | gas_consumption | electricity_consumption | ... |
Se il campo MongoDB data
modifica la sua definizione, il processo in background rileverà la versione dei dati ed elaborerà di conseguenza. Il database MySQL può essere ricreato dai dati MongoDB, possibilmente con un nuovo schema (se il futuro potrebbe richiederlo).
Situazione prevista
Nella nuova situazione, mi piacerebbe utilizzare un database di serie temporali (come suggerito da molte parti esterne). Ci sono due funzionalità che vorrei implementare a livello atomico (database):
- Gap filling per dati mancanti. È possibile che i dati trimestrali manchino di un paio di punti. Poiché i valori assoluti sono noti, questi dati devono essere riempiti linearmente.
- Memorizzazione di risoluzioni diverse. I dati verranno interrogati su più risoluzioni (da ora a anno) e tutte queste query dovrebbero essere veloci.
Requisiti:
- Dovrebbe scalare fino a un milione di dispositivi (immissione dati).
- Dovrebbe scalare fino a 50k utenti concorrenti (query di dati).
- I dati aggregati dovrebbero essere disponibili il prima possibile. (è accettabile fino a 1 ora)
- I dati potrebbero non deteriorarsi. (la cronologia completa dovrebbe essere disponibile alla massima risoluzione)
- I vecchi dati potrebbero essere aggiornati (alla massima risoluzione e tale modifica dovrebbe riflettersi su risoluzioni più basse). Questo è molto raro, ma dovrebbe essere possibile. (Se questo risulta essere un grosso problema, questo requisito potrebbe essere gestito in un altro modo, ma questa non è la soluzione preferita).
- Gratuito come nella birra gratis.
- I dati devono essere accessibili da NodeJS , poiché tutto il codice è scritto in NodeJS.
- Sarebbe preferibile se l'ultimo punto dati (l'anno corrente per esempio) fosse riempito con la somma dei livelli precedenti prima che fosse finito, altrimenti questo deve essere richiesto dalla tabella dei trimestri. Esempio: il 1 ° luglio 2017 il punto dati per il 2017 dovrebbe contenere la somma dell'anno fino a quella data, insieme a un'indicazione del tempo trascorso. (Questo è un piacere avere).
La query tipica assomiglia a questo (pseudo-codice):
SELECT <fields> BETWEEN <start-date> AND <end-date> WITH RESOLUTION <time-resolution>
.
Considerazioni correnti
Ho esaminato alcuni database che supportano le serie temporali (InfluxDB, MongoDB, Graphite, RRDtool, Redis, OpenTSDB, ...) ma non riesco a trovarne uno che supporti nativamente le diverse risoluzioni e / o il gap di riempimento .
MongoDB potrebbe essere un'opzione, ma la scrittura è fire-and-forget, il che significa che i dati mancanti potrebbero non essere rilevati. Per i dati grezzi, questo non è un problema, a patto che non si verifichi molto spesso. Per i dati elaborati, questo è un grosso problema, dal momento che il resto dell'applicazione presuppone che i dati in quelle tabelle siano sequenziali, anche in un caso limite non comune.
MySQL potrebbe anche essere un'opzione (ad esempio non modificare l'implementazione iniziale), ma mi sembra che i database delle serie temporali siano ottimizzati per un database delle serie temporali per un motivo.
Domanda
La situazione attuale è un buon approccio? E se non lo è, quale sarebbe migliore? Mi sembra che il mio caso d'uso non sia così unico nel mondo della memorizzazione delle serie temporali, ma non riesco a trovare alcuna risorsa online che possa darmi una spinta nella giusta direzione.