Un índice que hace referencia a varios campos es un Índice compuesto. Los índices compuestos pueden mejorar drásticamente los tiempos de respuesta de las consultas.
Las claves de índice corresponden a los campos del documento. En la mayoría de los casos, aplicar la Guía ESR (Igualdad, Ordenación, Rango) para organizar las claves del índice ayuda a crear un índice compuesto más eficiente.
Garantizar que los campos de igualdad siempre vayan primero. Aplicar la igualdad a los campos principales del índice compuesto permite aprovechar el hecho de que el resto de los valores de los campos están en orden. Se debe elegir si utilizar un campo de ordenación o de rango a continuación, según las necesidades específicas del índice:
Si evitar las ordenaciones en memoria es crítico, coloca los campos de ordenación antes de los campos de rango (ESR)
Si el predicado de rango en la query es muy selectivo, se debe colocar antes de los campos de ordenación (ERS)
Esta página presenta la Guía ESR. Para obtener más información sobre la optimización de consultas, consulte explainy planes de consulta.
Tip
Para obligar a MongoDB a usar un índice en particular, utiliza cursor.hint() (método mongosh) al probar los índices.
Igualdad
"Exacta" se refiere a una coincidencia exacta de un único valor. Las siguientes consultas de coincidencia exacta escanean la colección cars en busca de documentos cuyo campo model coincide exactamente con Cordoba.
db.cars.find( { model: "Cordoba" } ) db.cars.find( { model: { $eq: "Cordoba" } } )
Las búsquedas de índices hacen un uso eficiente de las coincidencias exactas para reducir el número de claves de índice examinadas. Los campos de igualdad deben ir primero. Cuando utilizas la primera parte del índice para la igualdad, el resto del índice permanece ordenado.
Un índice puede tener múltiples claves para query con coincidencias exactas. Las claves de índice para las coincidencias exactas pueden aparecer en cualquier orden. Sin embargo, para cumplir con una coincidencia exacta con el índice, todas las claves del índice para coincidencias exactas deben preceder a cualquier otro campo del índice. El algoritmo de búsqueda de MongoDB elimina la necesidad de colocar los campos de coincidencia exacta en un orden específico.
Cuanto más selectivas sean las coincidencias exactas, más eficiente será la consulta indexada.
Sort
"Ordenación" determina el orden de los resultados. Para evitar ordenaciones en memoria, coloca los campos de ordenación antes del rango en el índice.
Un índice puede admitir operaciones de ordenación cuando los campos de consulta son un subconjunto de las claves de índice. Las operaciones de ordenación en un subconjunto de las claves de índice solo son compatibles si la consulta incluye condiciones de igualdad para todas las claves de prefijo que preceden a las claves de ordenación. Para obtener más información, consulta Subconjunto de ordenación y sin prefijo de un índice.
El siguiente ejemplo consulta la colección cars. La salida está ordenada por model:
db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )
Para mejorar el rendimiento de query, crea un índice en los campos manufacturer y model:
db.cars.createIndex( { manufacturer: 1, model: 1 } )
manufactureres la primera clave porque es una coincidencia exacta.modelse indexa en el mismo orden (1) que la query.
Rango
Campos de escaneo de filtros de "rango". El escaneo no requiere una coincidencia exacta, lo que significa que los filtros de rango están vinculados de manera flexible a las claves de índice. Para mejorar la eficiencia de las consultas, limita los límites del rango y utiliza coincidencias exactas para reducir el número de documentos a escanear.
Los filtros de rango son similares a lo siguiente:
db.cars.find( { price: { $gte: 15000} } ) db.cars.find( { age: { $lt: 10 } } ) db.cars.find( { priorAccidents: { $ne: null } } )
Si el predicado de rango en la query es muy selectivo, se debe colocar antes de los campos de ordenación para reducir el número de documentos ordenados y permitir un ordenamiento en memoria.
Para evitar una ordenación en memoria, coloque el filtro de rango después del predicado de ordenación. Para obtener más información sobre las clasificaciones en memoria, consulte cursor.allowDiskUse().
Consideraciones adicionales
Los operadores de desigualdad tales como
$neo$ninson operadores de rango, no operadores exactos.$regexes un operador de rango.Cuando
$inse usa solo, es un operador de igualdad que realiza una serie de coincidencias exactas.Cuando
$inse usa con.sort():Si
$intiene menos de 201 elementos en el arreglo, los elementos se expanden y luego se combinan en el orden de clasificación especificado para el índice utilizando una etapaSORT_MERGE. Esto mejora el rendimiento de los arreglos pequeños. En este caso,$ines similar a un predicado de igualdad con ESR.Si
$intiene 201 elementos o más, los elementos se ordenan como un operador de rango. En este caso, no se realiza la mejora del rendimiento para arreglos pequeños. No es posible que los campos subsiguientes en el índice se utilicen para ordenar, y$ines similar a un predicado de rango con ESR.Si normalmente utiliza operadores
$incon arreglos pequeños, inclúyalos antes en la especificación del índice. Si normalmente utiliza arreglos grandes, incluya los operadores$indonde incluiría un predicado de rango.
Nota
No se garantiza que el cambio de comportamiento $in en los elementos del arreglo 201 se mantenga igual en todas las versiones de MongoDB.
Ejemplo
La siguiente query busca la colección cars de vehículos fabricados por Ford que cuesten más de 15.000 USD. Los resultados están clasificados por modelo:
db.cars.find( { manufacturer: 'Ford', cost: { $gt: 15000 } } ).sort( { model: 1 } )
El query contiene todos los elementos de la Guía ESR:
manufacturer: 'Ford'es una coincidencia basada en igualdadcost: { $gt: 15000 }es una coincidencia basada en un rango, ymodelse utiliza para la clasificación
Siguiendo la guía ESR, el índice óptimo para el query de ejemplo es:
{ manufacturer: 1, model: 1, cost: 1 }
Discusión adicional
Varias ponencias en conferencias de MongoDB abordan la regla ESR en profundidad.