Scansione di un miliardo di righe in un database ultraveloce


9

sfondo

Un database locale contiene quasi 1,3 miliardi di righe univoche. Ogni riga è indirettamente associata a una specifica latitudine e longitudine (posizione). Ogni riga ha un timbro data.

Caso d'uso

Il problema è il seguente:

  1. L'utente imposta una data di inizio / fine e un intervallo di valori (ad esempio, da 100 a 105).
  2. Il sistema raccoglie tutte le righe corrispondenti alla data specificata, raggruppate per posizione.
  3. Il sistema esegue determina le posizioni che, durante tali date, hanno una probabilità statistica di cadere nell'intervallo di valori indicato.
  4. Il sistema visualizza tutte le posizioni corrispondenti all'utente.

Questo è un problema di velocità e scala.

Domanda

Qual è l'architettura della soluzione meno costosa che puoi immaginare che consentirebbe a un tale sistema di recuperare risultati per gli utenti in meno di cinque secondi?

Sistema corrente

L'ambiente è attualmente:

  • PostgreSQL 8.4 (l'aggiornamento è possibile; la commutazione dei database non è un'opzione)
  • R e PL / R
  • XFS
  • WD VelociRaptor
  • 8 GB di RAM (Corsair G.Skill; 1.3 GHz)
  • Quad core GenuineIntel 7 (2,8 GHz)
  • Ubuntu 10.10

Gli aggiornamenti hardware sono accettabili.

Aggiornamento - Struttura del database

I miliardi di righe sono in una tabella simile a:

id | taken | location_id | category | value1 | value2 | value3
  • id: chiave primaria
  • presa: data assegnata alla riga
  • location_id - Riferimento alla latitudine / longitudine
  • categoria - Una descrizione dei dati
  • value1 .. 3 - Gli altri valori su cui l'utente può interrogare

La takencolonna è in genere date consecutive per location_id, a volte ogni posizione ha dati dal 1800 al 2010 (circa 77.000 date, molte delle quali duplicate poiché ogni posizione ha dati nello stesso intervallo di date).

Esistono sette categorie e le tabelle sono già suddivise per categoria (utilizzando le tabelle figlio). Ogni categoria contiene ~ 190 milioni di righe. Nel prossimo futuro, il numero di righe per categoria supererà il miliardo.

Ci sono circa 20.000 località e 70.000 città. Le posizioni sono correlate alla città per latitudine e longitudine. Assegnare ogni posizione a una particolare città significa trovare i confini della città, il che non è un compito banale.

idee

Alcune idee che ho includono:

  • Trova un servizio cloud per ospitare il database.
  • Crea una striscia raid SSD (ottimo video).
  • Crea una tabella che riunisce tutte le posizioni per città (pre-calcolo).

Grazie!


10
"Il cambio di database non è un'opzione" che elimina praticamente la maggior parte delle soluzioni. in bocca al lupo!
Steven A. Lowe,

1
È difficile dire senza ulteriori informazioni su cosa stai facendo esattamente con quei record. Inoltre, stai cercando il caso peggiore di 5 secondi (che probabilmente significa che ogni record esaminato e zero posizioni corrispondono)?
Guy Sirton

2
@Dave: quanto tempo impiega il sistema attuale? Il sistema attuale utilizza PostGIS ? È location_idun geographyo geometryoppure fa riferimento a una seconda tabella? La location_idcolonna è indicizzata?
rwong

1
@ Thorbjørn & @Darknight - Nella sezione idee elencherò il pre-calcolo, che ridurrebbe i dati a un valore per città al giorno (per categoria). Il calcolo potrebbe ripetersi annualmente, o anche mensilmente, suppongo. Questo era il mio piano se non ci fossero altre possibilità (i calcoli probabilmente impiegheranno settimane).
Dave Jarvis,

1
@Dave, molte possibilità, ma la domanda è: cosa ti interessa. Hai studiato dove si trovano ancora i colli di bottiglia attuali?

Risposte:


12

La cosa più importante è essere assolutamente certi di dove sia ora il collo di bottiglia per un determinato numero di richieste rappresentative poiché non è possibile cambiare database.

Se si eseguono scansioni complete delle tabelle, sono necessari indici appropriati.

Se aspetti l'I / O hai bisogno di più memoria per la memorizzazione nella cache (Jeff Atwood ha recentemente affermato che i sistemi a 24 Gb erano raggiungibili sui sistemi desktop).

Se aspetti sulla CPU devi vedere se i tuoi calcoli possono essere ottimizzati.

Ciò richiede un cappello DBA appuntito e un cappello del sistema operativo, ma ne vale la pena per assicurarsi di abbaiare l'albero giusto.


Tuttavia, se lo tagli e lo tagli, anche se ogni riga richiede solo 100 byte, 1,3 miliardi di righe = 121 GB. Con tutti i tuoi indici ecc., Sono sicuro che questo sarà molto di più. Su una singola scatola, sarai lento a meno che tu non abbia un hardware serio attorno a SSD + Tonnellate di RAM. Il modo più economico è ridimensionare le scatole.
Subu Sankara Subramanian,

4
@Subu, vuoi andare distribuito? Ora hai due problemi ...

Heh - che sono d'accordo :) Ma è più economico!
Subu Sankara Subramanian,

@ Thorbjørn: grazie per il tuo tempo e tutto il tuo aiuto. Penso che ridurrò il set di dati a 25 milioni di righe per categoria, quindi applicherò gli indici alla data. Ciò dovrebbe ridurre la scansione a ~ 70000 righe (al giorno, con un limite di due settimane per l'intervallo), che dovrebbe essere abbastanza scattante.
Dave Jarvis,

@Dave, devi ancora sapere dove sono i tuoi colli di bottiglia. Imparalo mentre non è necessario.

4

Che ne dici di partizionare la tabella in più pezzi situati su host diversi in base al timbro della data? Questo è scalabile in orizzontale e finché si dispone di un numero sufficiente di caselle, è possibile scrivere un piccolo motore di aggregazione su queste configurazioni.

Se vedi che l'indicatore della data sta cambiando troppo, puoi partizionare in base alle posizioni, sempre scalabile in orizzontale. (Spero che non aggiungano molte più latitudini / longitudini!)


Grazie per le idee. Ci sono potenzialmente 77.066 date e nuove date verranno aggiunte in futuro. Ho una sola macchina. Esistono 20.000 posizioni, ma la suddivisione per posizione non sarebbe utile perché i dati da analizzare coprono tutte le posizioni.
Dave Jarvis,

e in che modo l'utilizzo del cloud differisce dalla soluzione di cui sopra?
Chani,

Questo è quello che ho pensato anche io. Una sorta di partizione orizzontale in modo che la ricerca possa avvenire in parallelo su tutte le partizioni.
davidk01,

Dividere il giorno sarebbe probabilmente il più utile, risultando in 2562 tabelle separate (366 giorni x 7 categorie).
Dave Jarvis,

4

Lo scenario peggiore è che l'intervallo di date copre tutte le date nel database.

Stai cercando di leggere 1,3 miliardi di record e fare una sorta di analisi su ogni record rispetto ai valori immessi, su una macchina fisica, in meno di 5 secondi. Il risultato può essere qualsiasi posizione o nessuna: non si sa nulla in anticipo.

Dati questi parametri direi probabilmente impossibile.

Guarda il tuo disco rigido: la velocità massima sostenuta è inferiore a 150 MB / s. La lettura di 1,3 miliardi di dischi richiederà più di 5 secondi. Per quanto riguarda la CPU, non sarai in grado di eseguire alcun tipo di analisi statistica su 1,3 miliardi di record in 5 secondi.

La tua unica speranza (tm :-)) è trovare una sorta di funzione di ricerca basata sui valori inseriti dall'utente che restringerà la ricerca (di alcuni ordini di grandezza). È possibile calcolare questa funzione di ricerca offline. Senza sapere di più sugli esatti criteri di corrispondenza, non credo che nessuno possa dirti come farlo, ma un esempio potrebbe essere quello di suddividere l'intervallo di valori in un intervallo discreto e creare una ricerca che ti dia tutti i record in quell'intervallo. Finché l'intervallo è abbastanza piccolo, puoi fare un vero lavoro al suo interno, ad esempio eliminando le voci che non corrispondono al valore inserito dall'utente. Fondamentalmente lo spazio commerciale per il tempo.

Potrebbe essere possibile conservare tutti i record (o almeno la parte importante) in memoria. Probabilmente non in 8 GB. Questo eliminerà almeno la parte di I / O del disco sebbene anche la larghezza di banda della memoria possa essere insufficiente per scansionare tutto in 5 secondi. Ad ogni modo, questa è un'altra tecnica per accelerare questo tipo di applicazioni (combinare con il mio suggerimento precedente).

Hai menzionato l'utilizzo di un servizio cloud. Sì, se paghi abbastanza CPU e IO muscolare e dividi il database su molti server, puoi forzare / dividere e conquistarlo.


Grazie per la risposta. Gli aggiornamenti hardware sono una considerazione, secondo le idee che ho elencato. Una soluzione inferiore a $ 750 USD sarebbe l'ideale.
Dave Jarvis,

2

Secondo il commento di rwong alla domanda: PostgreSQL offre tipi e strumenti di indici appropriati (indici GIST, indici GIN, Postgis, tipi geometrici) in modo tale che geodati e dati relativi al datetime possano essere ricercati lungo quei criteri senza problemi.

Se le tue query su questi criteri impiegano pochi secondi, probabilmente significa che non vengono utilizzati tali indici. Puoi confermare che hai esaminato questi come appropriato?


Grazie. Le sette tabelle figlio sono raggruppate in base alla posizione, alla data e alla categoria usando un btree. L'anno scorso ho fatto ricerche sugli indici GIN e non mi hanno aiutato (o non avrebbero voluto), come ricordo.
Dave Jarvis,

2
La posizione dell'indicizzazione basata su B-Tree non è minimamente utile considerando il tipo di ricerche che stai esaminando. Hai bisogno di un indice invertito che funzioni con gli operatori necessari, che nel caso di Postgis di solito significa GIST. Potresti voler evidenziare alcune delle domande lente ...
Denis de Bernardy,

1

Dato che usi PostgreSQL e i dati di latitudine / longitudine, dovresti sicuramente usare anche PostGIS, in questo modo puoi aggiungere un indice spaziale GiST al tuo database per accelerare le cose.

Ho una tabella del genere (con 350k righe) con una configurazione molto più piccola della tua (2 core e appena 2Gb di RAM) ma le ricerche richiedono meno di un secondo.


0

Forse potresti rompere un modello relazionale come fece Essbase con la loro architettura OLAP: Essbase Wikipedia

Quello che voglio dire è creare una tabella per città, finendo così con oltre 1000 tabelle. Non un tavolo come hai suggerito, ma molti. Indicizza ogni tabella per data e posizione. Molte tabelle, molti indici -> più veloce.


Grazie per la nota. Ci sono oltre 70.000 città e molti valori di latitudine / longitudine diversi ricadono all'interno di un'area specifica della città.
Dave Jarvis,

@Dave: puoi costruire un diagramma voronoi per le città e classificare i valori lat / lon in tassellature? (cioè se sembra casuale, lascia che sia.) Quindi, durante la ricerca, cercherai tutte le città la cui tassellatura tocca le gamme lat / lon della query. Se la tassellatura di voronoi è troppo lenta, vale la pena provare scatole quadrate (ad es. 5 gradi lat x 5 gradi lon).
rwong,

0

Per quanto riguarda la tua idea di trovare un servizio cloud per ospitare il database, hai già incontrato SimpleGeo ? Hanno appena tagliato la barra multifunzione su un servizio di archiviazione apparentemente "appositamente ottimizzato per archiviare e interrogare i dati sulla posizione in modo molto, molto veloce" - sebbene il costo per archiviare e interrogare su oltre miliardi di righe potrebbe rendere questo approccio irrealizzabile.


-2

ti aspetti che una bicicletta corra in autostrada. attualmente stai cercando una soluzione per affrontare solo questo problema, non stai prevedendo il problema e se avessi 2 miliardi di dischi? la scalabilità deve essere affrontata. la risposta è un database di oggetti di semplice utilizzo. ad es. cache Intersystems

e credimi, non vengo dagli intersistemi ;-)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.