Docs Menu
Docs Home
/ /
Conceptos CRUD

Optimización de consultas

La optimización de queries mejora la eficiencia de las operaciones de lectura al reducir la cantidad de datos que las operaciones de queries deben procesar. Se pueden utilizar índices, proyecciones y límites de queries para mejorar el rendimiento de los queries y reducir el consumo de recursos.

Crear Índices para consultas frecuentes. Si una consulta busca en varios campos, cree un índice compuesto. Usar un índice mejora el rendimiento, ya que sin él, la consulta debe analizar todos los documentos de la colección.

Por ejemplo, considere la siguiente consulta sobre el type campo en la colección inventory:

let typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

Para mejorar el rendimiento de este query, agregar un índice a la colección inventory en el campo type. [1] En mongosh, crear índices utilizando el método db.collection.createIndex():

db.inventory.createIndex( { type: 1 } )

Para analizar el rendimiento de las consultas, consulte Analizar el rendimiento de las consultas.

[1] En los índices de un solo campo, el orden del índice no importa. En los índices compuestos, el orden de los campos influye en las consultas que admite el índice. Para más información, consulte Orden de clasificación.

La selectividad del query se refiere a qué tan bien el predicado del query filtra los documentos de una colección. La selectividad del query determina si las queries pueden usar los índices de manera efectiva.

Los queries más selectivos coinciden con un porcentaje menor de documentos. Por ejemplo, una coincidencia exacta en el campo único _id es altamente selectiva, ya que puede coincidir como máximo con un documento.

Los queries menos selectivos coinciden con un porcentaje mayor de documentos y no pueden utilizar los índices de manera eficaz.

Por ejemplo, los operadores de desigualdad $nin y $ne no son muy selectivos, ya que a menudo coinciden con una gran parte del índice. Como resultado, en muchos casos, un query $nin o $ne con un índice puede no tener un mejor desempeño que un query $nin o $ne que debe escanear todos los documentos de una colección.

La selectividad de regular expressions depende de las expresiones en sí mismas. Para aprender más, se puede consultar uso de expresiones regulares e índice.

Cuando se necesita un subconjunto de campos de documentos, se puede mejorar el rendimiento devolviendo solo los campos que son necesarios. Las proyecciones disminuyen el tráfico de red y el tiempo de procesamiento.

Por ejemplo, si el query para la colección posts solo necesita los campos timestamp, title, author y abstract, se deben especificar esos campos en la proyección:

db.posts.find(
{},
{ timestamp : 1, title : 1, author : 1, abstract : 1}
).sort( { timestamp : -1 } )

Cuando se usa una etapa de agregación $project, normalmente debería ser la última etapa del pipeline y se utiliza para especificar qué campos devolver al cliente.

Usar una etapa $project al principio o en medio de un pipeline para reducir el número de campos que se pasan a las etapas posteriores del pipeline es poco probable que mejore el rendimiento, ya que la base de datos realiza esta optimización automáticamente.

Para aprender más sobre el uso de las proyecciones, consultar Campos de proyecto a devolver del query.

Los cursores de MongoDB devuelven resultados en agrupación. Si sabe cuántos resultados se desean, se puede especificar ese valor en el método limit(). Limitar los resultados reduce la demanda sobre los recursos de la red.

En general, limitar los resultados es más útil cuando los resultados están ordenados, de modo que se sepa qué documentos se devolverán. Por ejemplo, si solo se necesitan 10 resultados de la query a la colección posts, se ejecuta el siguiente query:

db.posts.find().sort( { timestamp : -1 } ).limit(10)

Para aprender más sobre cómo limitar los resultados, se puede consultar limit().

El optimizador del query normalmente selecciona el índice óptimo para una operación específica. Sin embargo, se puede forzar a MongoDB a usar un índice específico usando el método hint(). Utilizar hint() para dar soporte a las pruebas de rendimiento o cuando se puede consultar un campo que aparece en varios índices para garantizar que MongoDB utilice el índice correcto.

Utilizar el operador $inc de MongoDB para incrementar o disminuir valores en los documentos. El operador incrementa el valor del campo en el lado del servidor, como alternativa a seleccionar un documento, realizar modificaciones simples en el cliente y luego guardar todo el documento en el servidor. El operador $inc también puede ayudar a evitar las condiciones de competencia que ocurren cuando dos instancias de la aplicación hacen un query a un documento, incrementan un campo manualmente y guardan todo el documento al mismo tiempo.

Un query cubierto es un query que se puede satisfacer en su totalidad mediante un índice y no tiene que examinar ningún documento. Un índice cubre un query cuando se aplican todas las siguientes condiciones:

  • Todos los campos del query (tanto los especificados por la aplicación como los necesarios internamente, como para fines de partición) son parte de un índice.

  • Todos los campos devueltos en los resultados están en el mismo índice.

  • Ningún campo en el query es igual a null. Por ejemplo, los siguientes predicados de queries no pueden dar lugar a queries cubiertos:

    • { "field": null }

    • { "field": { $eq: null } }

Una colección de inventory tiene el siguiente índice en los campos type y item:

db.inventory.createIndex( { type: 1, item: 1 } )

El índice cubre la siguiente operación que hace queries en los campos type y item y devuelve solo el campo item:

db.inventory.find(
{ type: "food", item:/^c/ },
{ item: 1, _id: 0 }
)

Para que el índice especificado cubra el query, el documento de proyección debe especificar explícitamente _id: 0 para excluir el campo _id del resultado, ya que el índice no incluye el campo _id.

Un índice puede cubrir un query sobre campos dentro de documentos incrustados.

Por ejemplo, considere una colección userdata con documentos de la siguiente forma:

db.userdata.insertOne(
{ _id: 1, user: { login: "tester" } }
)

La colección tiene el siguiente índice:

db.userdata.createIndex(
{ "user.login": 1 }
)

El índice { "user.login": 1 } cubre el siguiente query:

db.userdata.find(
{ "user.login": "tester" },
{ "user.login": 1, _id: 0 }
)

Nota

Para indexar campos en documentos incrustados, se debe utilizar notación de puntos. Consultar Crear un Índice en un campo incrustado.

Los índices multiclave pueden cubrir queries sobre campos que no son arreglos si el índice rastrea qué campo o campos hacen que el índice sea multiclave.

Índices multiclave no pueden cubrir consultas sobre campos de arreglos.

Para ver un ejemplo de un query cubierto con un índice multiclave, se puede consultar Queries cubiertos en la página de índices multiclave.

Debido a que el índice contiene todos los campos requeridos por el query, MongoDB puede hacer coincidir las condiciones del query y devolver los resultados utilizando solo el índice.

Consultar únicamente el índice puede ser mucho más rápido que consultar documentos fuera del índice. Las claves de índice suelen ser más pequeñas que los documentos que catalogan, y los índices suelen estar disponibles en la RAM o ubicados secuencialmente en el disco.

No todos los tipos de índice pueden cubrir queries. Para obtener detalles sobre el soporte de índices cubiertos, se puede consultar la página de documentación del tipo de índice correspondiente.

Cuando se ejecuta en mongos, los índices solo pueden cubrir queries en las colecciones particionadas si el índice contiene la clave de partición.

Para determinar si un query es un query cubierto, se debe utilizar el método db.collection.explain() o el método explain(). Ver Queries cubiertos.

Volver

Coherencia causal

Obtén una insignia de habilidad

¡Domina "Query Optimization" gratis!

Más información

En esta página