2013-07-19 8 views
15

Ho bisogno di memorizzare diversi miliardi di piccole strutture di dati (circa 200 byte ciascuna). Finora, la memorizzazione di ciascun elemento come documento separato sta funzionando bene, con Mongo che fornisce circa 10.000 risultati al secondo. Sto usando un hash da 20 byte come _id per ogni documento e un singolo indice sul campo _id. Nei test, questo funziona per set di dati con 5.000.000 di documenti.Strategie per ricerche veloci di miliardi di piccoli documenti in MongoDB

Nel funzionamento, faremo circa 10.000 richieste al secondo, aggiornando i documenti esistenti circa 1.000 volte al secondo e inserendo nuovi documenti forse 100 volte al secondo o meno.

Come possiamo gestire set di dati più grandi, quando non è possibile memorizzare un intero indice nella RAM? MongoDB funzionerà meglio se combiniamo diversi elementi in ogni documento - per una ricerca più rapida attraverso l'indice, ma più dati vengono restituiti in ogni query?

A differenza di altre domande su SO, non sono interessato solo a quanti dati possiamo inserire in Mongo. Può gestire chiaramente la quantità di dati che stiamo osservando. La mia preoccupazione è come possiamo massimizzare la velocità delle operazioni find su enormi raccolte, data la RAM limitata.

Le nostre ricerche tendono ad essere raggruppate; circa 50.000 elementi soddisferanno circa il 50% delle query, ma il restante 50% verrà distribuito casualmente su tutti i dati. Possiamo aspettarci un guadagno in termini di prestazioni spostando il 50% nella propria collezione, al fine di mantenere sempre un indice più piccolo dei dati più utilizzati nella ram?

La riduzione della dimensione del campo _id da 20 byte a 8 byte ha un impatto significativo sulla velocità di indicizzazione di MnogoDB?

+0

Dal momento che sembra che ci siano molti più documenti della RAM, ridurrei i documenti il ​​più possibile per aumentare la quantità di dati che possono essere contenuti nella RAM. Ad esempio, assicurati che i nomi dei campi siano solo uno o due caratteri. Stai pianificando di sharding? Lo spostamento dei dati in una raccolta distinta sullo stesso server non cambierà l'utilizzo della RAM, poiché è comunque gestito dal sistema operativo. – WiredPrairie

+0

Divideremo mentre i dati crescono. – Neil

+0

Inserire i record più utilizzati in una raccolta diversa è solo un'idea, al fine di mantenere l'indice per questa raccolta più piccola nella RAM e cercare di evitare che venga scambiato. Penso che questo potrebbe essere ingenuo, ma non sono sicuro del perché o perché no. – Neil

risposta

17

Poche strategie vengono in mente:

1) Utilizzare un netto di raccolta/database per i documenti 'caldi'.

Se si conoscono i documenti nel set caldo, sì, spostarli in una raccolta separata sarà d'aiuto. Ciò garantirà che i documenti caldi siano co-residenti sulle stesse estensioni/pagine. Renderà anche l'indice per quei documenti più probabile che sia completamente in memoria. Ciò è dovuto al fatto che è più piccolo e viene utilizzato (completamente?) Più spesso.

Se i documenti caldi sono mescolati in modo casuale con altri documenti, è probabile che si verifichi un errore in più degli elementi foglia dell'indice B-Tree quando si carica un documento come probabilità di un altro documento che ha recentemente caricato o ha avuto accesso all'indice il blocco è piccolo.

2) Accorciare i valori indicizzati.

Più breve è il valore dell'indice più valori si adattano a un singolo blocco B-Tree. (Nota: le chiavi non sono incluse nell'indice.) Più voci in un singolo bucket significano meno bucket e meno memoria totale necessaria per l'indice. Ciò si traduce in probabilità più elevate/tempi di vita più lunghi che i blocchi rimarranno nella memoria. Nel tuo esempio una riduzione di 20-> 8 caratteri è un risparmio migliore del 50%. Se riesci a convertire questi 8 byte in un lungo, c'è un po 'più di risparmio dato che i long non hanno un prefisso di lunghezza (4 byte) e un null finale (5 byte totali).

3) Abbreviare i nomi dei tasti.

Più breve è il nome del campo, minore è lo spazio occupato da ciascun documento. Questo ha lo sfortunato effetto collaterale di diminuire la leggibilità.

4) Shard

Questo è davvero l'unico modo per mantenere le prestazioni fino a fronte di legge attraverso un intero corpus che esaurisce la memoria e larghezza di banda del disco eventuale. Se fai lo shard, vorrai comunque ritagliare la raccolta "hot".

5) Adjust the read-ahead on disk to a small value.

Dal momento che il 'non hot', si legge deve caricare un documento a caso da disco abbiamo davvero solo vogliamo leggere/errore nella memoria che documentano e, come alcuni dei documenti intorno ad esso il più possibile. La maggior parte dei sistemi proverà a leggere un grande blocco di dati quando un utente legge da una porzione di un file. Questo è esattamente l'opposto di quello che vogliamo.

Se il sistema si guasta molto ma la memoria residente per il processo mongod non si avvicina alla memoria disponibile del sistema, è probabile che si veda l'effetto del sistema operativo che legge dati inutili.

6) Provare a utilizzare valori monotonicamente crescenti per i tasti.

Ciò attiverà un'ottimizzazione (per gli indici basati su ObjectId) che quando il blocco dell'indice si suddivide, lo farà a 90/10 anziché a 50/50. Il risultato è che la maggior parte dei blocchi nel tuo indice sarà vicino alla capacità e ne avrai bisogno di meno.

Se si conoscono solo i "caldi" 50.000 documenti dopo il fatto, quindi l'aggiunta alla raccolta separata nell'ordine dell'indice attiverà anche questa ottimizzazione.

Rob.

Problemi correlati