sql >> Base de Datos >  >> NoSQL >> MongoDB

La consulta de Mongo lleva mucho tiempo. ¿Cómo hacerlo más rápido?

El índice debería cubrir todas las partes de la consulta (parte de igualdad, parte de clasificación y parte de rango). Esto se debe a que en un típico find() consulta, MongoDB solo usa un índice. Por ejemplo, generalmente no usa un índice para la parte de igualdad y otro índice para la parte de clasificación.

En general, la secuencia de campos en el índice debe seguir el patrón de igualdad -> ordenar -> rango .

Esto se describe en detalle en Optimización de índices compuestos de MongoDB .

Para su consulta, la parte de igualdad es tag:..., letterId:... y la parte de clasificación es emailId:-1 . No hay una parte de rango en su consulta.

Usando este patrón, el índice compuesto que necesita es:

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

Intentemos confirmar cuánta mejora de rendimiento podemos obtener usando este índice.

Datos de prueba

Para confirmar la idoneidad del índice, inserté 1 millón de registros en una base de datos de prueba usando mgeneratejs , que es una herramienta para crear un documento aleatorio usando una plantilla.

Según su ejemplo, mgeneratejs plantilla que estoy usando es:

$ 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 importó 1 millón de documentos aleatorios a MongoDB:

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

Prueba 1:índice no óptimo

Luego creé el índice que tiene e intenté encontrar un documento inexistente y reuní 10 ejecuciones de la consulta con la colección que contiene solo este índice:

> 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

por lo tanto, al usar ese índice, los tiempos de respuesta de la consulta no son excelentes, y la mayoría de las ejecuciones se acercan a los 3 segundos.

Prueba 2:igualdad -> ordenar -> índice de rango

Agregando la igualdad -> ordenar -> rango óptimo índice:

> 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

Por el contrario, utilizando el índice óptimo, el rendimiento mejoró notablemente. Ninguna consulta devolvió en más de 3ms, con la gran mayoría de las veces regresa en 1ms.