In che modo la proiezione mongoDB influisce sulle prestazioni?


10

Dalla MongoDBdocumentazione si dice che:

Quando è necessario solo un sottoinsieme di campi dai documenti, è possibile ottenere prestazioni migliori restituendo solo i campi necessari

In che modo i campi di filtro influiscono sulle prestazioni? Le prestazioni sono correlate alla dimensione dei dati trasmessi sulla rete? o la dimensione dei dati che verranno conservati in memoria? Come viene migliorata esattamente questa prestazione? Qual è questa prestazione menzionata nella documentazione?

Ho domande lente su MongoDB. La restituzione di un sottoinsieme influisce sulla mia query lenta (ho un indice composto sul campo)?


Senza il codice, non è possibile suggerirti. cosa influenzerà effettivamente le prestazioni nella query di proiezione "MongoDB". È sempre meglio almeno menzionare il codice.
Haidar Ali Khan,

@MdHaidarAliKhan non si tratta del codice e del mio payload. Voglio solo sapere perché mongoDB afferma che il filtro influisce sulle prestazioni? Da quale punto di vista questa prestazione è stata misurata? Ad esempio, aiuta sull'utilizzo della memoria di Mongo a causa di meno dati o meno IO del disco (ad esempio) e così via.
ALH,

Voglio solo sapere perché mongoDB afferma che il filtro influisce sulle prestazioni? bene, utilizzare le proiezioni per restituire solo i dati necessari, intendo dire che è possibile ottenere prestazioni migliori restituendo solo i campi necessari. Ad esempio db.posts.find ({}, {}). Sort ({}).
Haidar Ali Khan,

Ad esempio, aiuta sull'utilizzo della memoria di Mongo a causa di meno dati o meno IO del disco (ad esempio) e così via, beh ... potresti aggiornare quale versione di MongoDB e sistema operativo nel tuo ambiente?
Haidar Ali Khan,

@MdHaidarAliKhan OS is Debian 8,MongoDB 3.6.2
ALH,

Risposte:


15

Per impostazione predefinita, le query restituiscono tutti i campi nei documenti corrispondenti. Se sono necessari tutti i campi, la restituzione di documenti completi sarà più efficiente rispetto al fatto che il server manipoli il set di risultati con criteri di proiezione.

Tuttavia, l'utilizzo della proiezione per limitare i campi da restituire dai risultati della query può migliorare le prestazioni:

  • rimozione dei campi non necessari dai risultati della query (risparmio sulla larghezza di banda della rete)
  • limitazione dei campi dei risultati per ottenere una query coperta (restituzione dei risultati della query indicizzata senza recupero di documenti completi)

Quando si utilizza la proiezione per rimuovere i campi non utilizzati, il server MongoDB dovrà recuperare tutti i documenti completi in memoria (se non è già presente) e filtrare i risultati per restituirli. Questo uso della proiezione non riduce l'utilizzo della memoria o il working set sul server MongoDB, ma può salvare una larghezza di banda di rete significativa per i risultati delle query in base al modello di dati e ai campi proiettati.

Una query coperta è un caso speciale in cui tutti i campi richiesti in un risultato della query sono inclusi nell'indice utilizzato, quindi il server non deve recuperare l'intero documento. Le query coperte possono migliorare le prestazioni (evitando il recupero di documenti) e l'utilizzo della memoria (se altre query non richiedono il recupero dello stesso documento).

Esempi

A scopo dimostrativo tramite la mongoshell, immagina di avere un documento simile al seguente:

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

Il campo bpotrebbe rappresentare una selezione di valori (o in questo caso una stringa molto lunga).

Quindi, crea un indice su {a:1}cui si trova un campo comunemente usato richiesto dal tuo caso d'uso:

db.data.createIndex({a:1})

Un semplice findOne()senza criteri di proiezione restituisce un risultato della query di circa 10 MB:

> bsonsize(db.data.findOne({}))
10485805

L'aggiunta della proiezione {a:1}limiterà l'output al campo ae al documento _id(incluso per impostazione predefinita). Il server MongoDB sta ancora manipolando un documento da 10 MB per selezionare due campi, ma il risultato della query ora è di soli 33 byte:

> bsonsize(db.data.findOne({}, {a:1}))
33

Questa query non è coperta perché è necessario recuperare l'intero documento per scoprire il _idvalore. Il _idcampo è incluso nei risultati della query per impostazione predefinita poiché è l'identificatore univoco di un documento, ma _idnon verrà incluso in un indice secondario se non viene aggiunto esplicitamente.

Le metriche totalDocsExaminede totalKeysExaminednei explain()risultati mostreranno quanti documenti e chiavi di indice sono stati esaminati:

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

Questa query può essere migliorata utilizzando la proiezione per escludere il _idcampo e ottenere una query coperta utilizzando solo l' {a:1}indice. La query coperta non deve più recuperare un documento di ~ 10 MB in memoria, quindi sarà efficiente nell'uso della rete e della memoria:

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

Ho domande lente su MongoDB. La restituzione di un sottoinsieme influisce sulla mia query lenta (ho un indice composto sul campo)?

Non è possibile rispondere senza il contesto di una query specifica, un documento di esempio e l'output esplicativo completo. Tuttavia, è possibile eseguire alcuni benchmark nel proprio ambiente per la stessa query con e senza proiezione per confrontare il risultato. Se la tua proiezione sta aggiungendo un notevole sovraccarico al tempo complessivo di esecuzione della query (elaborazione e trasferimento dei risultati), questo potrebbe essere un forte suggerimento che il tuo modello di dati potrebbe essere migliorato.

Se non è chiaro il motivo per cui una query è lenta, sarebbe meglio pubblicare una nuova domanda con dettagli specifici per indagare.


1
Apprezzo molto per la spiegazione approfondita del problema. Sembra che non sia possibile avere query coperte in quanto la mia risposta contiene molti più dati che all'interno dell'indice. La mia domanda principale è qui, sarei felice se potessi dare un'occhiata: dba.stackexchange.com/questions/195065/…
ALH,

1

Con una proiezione, è possibile ottenere una situazione in cui il set di risultati proviene direttamente dall'indice.

Se si dispone di un indice composto in {x:1, y:1, z:1}cui nessuno di x, y, z è _id, è necessario proiettare {_id:0, x:1, y:1, z:1}perché _idviene sempre restituito come parte del set di risultati (quando non viene proiettato via) e il motore deve leggere i file di dati per ottenerlo. Questo perché, indice non ha valore di _id, solo puntatore a quel documento in cui è memorizzato il valore.


Quindi, se rimuovo _iddalla risposta restituita, si adatta alla RAM? Questo aiuta?
ALH,

1
MongoD (cerca) di mantenere almeno gli indici in memoria (e quanti più dati si adattano). Se la query può essere compilata direttamente dall'indice e si proietta, il _id:0risultato viene restituito completamente dalla RAM, senza leggere i dati dal disco.
JJussi,
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.