PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Django + Postgres + Grandi serie storiche

Se ho capito correttamente i tuoi pensieri, stai considerando di archiviare le serie temporali in PostgreSQL, un record di serie temporali in una riga del database. Non farlo.

Da un lato, il problema è teorico. I database relazionali (e penso che la maggior parte dei database) si basano sulla premessa dell'indipendenza di riga, mentre i record di una serie temporale sono ordinati fisicamente. Naturalmente, gli indici del database forniscono un certo ordine per le tabelle del database, ma quell'ordine ha lo scopo di accelerare la ricerca o presentare i risultati in ordine alfabetico o in qualche altro ordine; non implica alcun significato naturale per quell'ordine. Indipendentemente da come li ordini, ogni cliente è indipendente dagli altri clienti e l'acquisto di ogni cliente è indipendente dagli altri suoi acquisti, anche se puoi ottenerli del tutto cronologicamente per formare la cronologia degli acquisti del cliente. L'interdipendenza dei record delle serie temporali è molto più forte, il che rende inappropriati i database relazionali.

In pratica, ciò significa che lo spazio su disco occupato dalla tabella e dai suoi indici sarà enorme (forse 20 volte maggiore rispetto alla memorizzazione delle serie temporali nei file) e la lettura delle serie temporali dal database sarà molto lenta, qualcosa come un ordine di grandezza più lenta rispetto alla memorizzazione nei file. Inoltre, non ti darà alcun vantaggio importante. Probabilmente non eseguirai mai la query "dammi tutti i record di serie temporali il cui valore è maggiore di X". Se mai avrai bisogno di una query del genere, avrai anche bisogno di un sacco di altre analisi che il database relazionale non è stato progettato per eseguire, quindi leggerai comunque l'intera serie temporale in qualche oggetto.

Quindi ogni serie temporale dovrebbe essere archiviata come un file. Potrebbe essere un file nel file system o un BLOB nel database. Nonostante io abbia implementato il secondo, credo che il primo sia migliore; in Django, scriverei qualcosa del genere:

class Timeseries(models.model):
    name = models.CharField(max_length=50)
    time_step = models.ForeignKey(...)
    other_metadata = models.Whatever(...)
    data = models.FileField(...)

Utilizzando un FileField renderà il tuo database più piccolo e renderà più semplice eseguire backup incrementali del tuo sistema. Sarà anche più facile ottenere fette cercando nel file, cosa che probabilmente è impossibile o difficile con un blob.

Ora, che tipo di file? Ti consiglio di dare un'occhiata ai panda. È una libreria Python per l'analisi matematica che supporta le serie temporali e dovrebbe anche avere un modo per archiviare le serie temporali nei file.

Ho collegato sopra a una mia libreria che non ti consiglio di usare; da un lato non fa quello che vuoi (non può gestire la granularità più fine di un minuto e ha altri difetti), e dall'altro è obsoleto - l'ho scritto prima dei panda e ho intenzione di convertirlo usare i panda in futuro. C'è un libro, "Python per l'analisi dei dati", dell'autore di panda, che ho trovato prezioso.

Aggiornamento (2016): C'è anche InfluxDB. Mai usato e quindi non ho opinioni, ma è sicuramente qualcosa che devi esaminare se ti stai chiedendo come memorizzare le serie temporali.

Aggiornamento (07-02-2020): C'è anche TimescaleDB, un'estensione di PostgreSQL.

Aggiornamento (07-08-2020): Abbiamo modificato il nostro software (di nuovo) in modo che memorizzi i dati nel database utilizzando TimescaleDB. Siamo già esperti in PostgreSQL ed è stato facile imparare un po' di TimescaleDB. Il vantaggio concreto più importante è che possiamo fare query come "trova tutti i luoghi in cui c'erano più di 50 mm di pioggia entro 24 ore nel 2019", cosa che sarebbe molto difficile quando si archiviano i dati in file flat. Un altro vantaggio sono i controlli di integrità:nel corso degli anni abbiamo avuto alcune serie temporali con righe duplicate a causa di piccoli bug qua e là. Anche gli svantaggi sono significativi. Utilizza 10 volte più spazio su disco. Potrebbe essere necessario modificare la nostra politica di backup di PostgreSQL per questo motivo. È più lento. Ci vuole forse un secondo per recuperare una serie temporale con 300.000 record. Questo è stato un istante prima. Avevamo bisogno di implementare la memorizzazione nella cache per recuperare le serie temporali, cosa che prima non era necessaria.