MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

La query Mongo richiede molto tempo. Come renderlo più veloce?

L'indice dovrebbe coprire tutta la parte della query (parte di uguaglianza, parte di ordinamento e parte di intervallo). Questo perché in un tipico find() query, MongoDB utilizza solo un indice. Ad esempio, generalmente non utilizza un indice per la parte di uguaglianza e un altro indice per la parte di ordinamento.

In generale, la sequenza dei campi nell'indice deve seguire lo schema di uguaglianza -> ordinamento -> intervallo .

Questo è descritto in dettaglio in Ottimizzazione degli indici composti MongoDB .

Per la tua query, la parte di uguaglianza è tag:..., letterId:... e la parte di ordinamento è emailId:-1 . Non c'è alcuna parte di intervallo nella tua query.

Utilizzando questo modello, l'indice composto di cui hai bisogno è:

db.test.createIndex({tag:1, letterId:1, emailId:-1})

Proviamo a confermare quanto miglioramento delle prestazioni possiamo ottenere utilizzando questo indice.

Dati di prova

Per confermare l'idoneità dell'indice, ho inserito 1 milione di record in un database di test utilizzando mgeneratejs , che è uno strumento per creare un documento casuale utilizzando un modello.

Sulla base del tuo esempio, mgeneratejs il modello che sto usando è:

$ cat template.json
{
  "emailId": "$hash",
  "email": "$email",
  "letterId": "$hash",
  "sendedFrom": "$email",
  "resultMsg": "$word",
  "owner": "$name",
  "created": "$date",
  "result": "$bool",
  "tag": "$word",
  "tryNum": {"$integer": {"min": 0, "max": 1e3}},
  "clickHash": "$word",
  "links": {"$array": {"of": "$url", "number": {"$integer": {"min": 1, "max": 5}}}}
}

e importato 1 milione di documenti casuali in MongoDB:

$ mgeneratejs template.json -n 1000000 | mongoimport -d test -c test

Test 1:indice non ottimale

Quindi creo l'indice che hai e provo a trovare un documento inesistente e raccolgo 10 esecuzioni della query con la raccolta contenente solo questo indice:

> db.test.createIndex({emailId: 1, letterId: 1, result: 1, owner: 1, tag: 1, clickHash: 1})

> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 3069ms
Fetched 0 record(s) in 2924ms
Fetched 0 record(s) in 2923ms
Fetched 0 record(s) in 3013ms
Fetched 0 record(s) in 2917ms
Fetched 0 record(s) in 2961ms
Fetched 0 record(s) in 2882ms
Fetched 0 record(s) in 2870ms
Fetched 0 record(s) in 2969ms
Fetched 0 record(s) in 2863ms

quindi usando quell'indice, i tempi di risposta della query non sono ottimi, con la maggior parte dell'esecuzione vicino a 3 secondi.

Test 2:uguaglianza -> ordinamento -> indice intervallo

Aggiungendo l'uguaglianza -> ordinamento -> intervallo ottimale indice:

> db.test.createIndex({tag:1, letterId:1, emailId:-1})

> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 2ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 3ms

Al contrario, utilizzando l'indice ottimale, la performance è stata notevolmente migliorata. Nessuna query restituita in più di 3 ms, la maggior parte delle volte viene restituita in 1 ms.