Archiviazione efficiente di serie temporali a più risoluzioni

6

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.

    
posta Martijn Verbakel 01.03.2017 - 17:58
fonte

1 risposta

2

Ho lavorato a un'applicazione simile per la California Energy Commission (UT3 o Universal Translator 3). Un paio di punti:

  • L'algoritmo di "compilazione" potrebbe non essere corretto matematicamente. I dati in questione sono in genere valori medi. Il modo corretto di ricampionare nel tempo, dati di valore medio, è utilizzare una media ponderata nel tempo. È un tipo di integrazione.
  • D'altra parte, potresti avere alcuni dati di tipo istantanei, che richiedono un diverso tipo di integrazione numerica. Ti suggerisco di studiare le proprietà matematiche più strettamente necessarie.
  • Le migliori prestazioni deriveranno dall'utilizzo di un database personalizzato che memorizza solo i dati originali, non ricampionati, in formato binario. Un "database personalizzato" può consistere in un insieme di file di sola lettura, ognuno dei quali contiene un flusso di dati. Un database specifico per serie temporali è probabilmente abbastanza veloce.
  • Gli algoritmi di ricampionamento sono abbastanza veloci da poter essere eseguiti in tempo reale sul client.
  • Se la frequenza di campionamento dell'utente finale è molto inferiore rispetto ai dati originali, ovviamente è logico memorizzare nella cache i flussi di ricampionamento sul server. L'accesso ai dati originali rende i progetti basati su client (come Universal Translator) più accattivanti per alcuni usi.
risposta data 07.03.2017 - 17:42
fonte

Leggi altre domande sui tag