De la MongoDB
documentación se menciona que:
Cuando solo necesita un subconjunto de campos de documentos, puede lograr un mejor rendimiento devolviendo solo los campos que necesita
¿Cómo afectan los campos de filtrado al rendimiento? ¿El rendimiento está relacionado con el tamaño de los datos que se transmiten a través de la red? o el tamaño de los datos que se guardarán en la memoria? ¿Cómo se mejora exactamente este rendimiento? ¿Cuál es este rendimiento que se menciona en la documentación?
Tengo consultas lentas de MongoDB. ¿Devolver un subconjunto afecta mi consulta lenta (tengo un índice compuesto en el campo)?
mongodb
projection
ALH
fuente
fuente
Debian 8
,MongoDB 3.6.2
Respuestas:
Por defecto, las consultas devuelven todos los campos en documentos coincidentes. Si necesita todos los campos, devolver documentos completos será más eficiente que hacer que el servidor manipule el conjunto de resultados con criterios de proyección.
Sin embargo, usar la proyección para limitar los campos para regresar de los resultados de la consulta puede mejorar el rendimiento al:
Cuando se utiliza la proyección para eliminar los campos no utilizados, el servidor MongoDB tendrá que recuperar cada documento completo en la memoria (si aún no está allí) y filtrar los resultados para volver. Este uso de la proyección no reduce el uso de memoria o el conjunto de trabajo en el servidor MongoDB, pero puede ahorrar un ancho de banda de red significativo para los resultados de la consulta, dependiendo de su modelo de datos y los campos proyectados.
Una consulta cubierta es un caso especial en el que todos los campos solicitados en un resultado de consulta se incluyen en el índice utilizado, por lo que el servidor no tiene que recuperar el documento completo. Las consultas cubiertas pueden mejorar el rendimiento (evitando recuperar documentos) y el uso de memoria (si otras consultas no requieren recuperar el mismo documento).
Ejemplos
Para fines de demostración a través del
mongo
shell, imagine que tiene un documento que se ve así:El campo
b
puede representar una selección de valores (o en este caso una cadena muy larga).A continuación, cree un índice en el
{a:1}
que sea un campo de uso común consultado por su caso de uso:Un simple
findOne()
sin criterios de proyección devuelve un resultado de consulta que es de aproximadamente 10 MB:Agregar la proyección
{a:1}
limitará la salida al campoa
y al documento_id
(que se incluye por defecto). El servidor MongoDB todavía está manipulando un documento de 10 MB para seleccionar dos campos, pero el resultado de la consulta ahora es de solo 33 bytes:Esta consulta no está cubierta porque se debe buscar el documento completo para descubrir el
_id
valor. El_id
campo se incluye en los resultados de la consulta de forma predeterminada, ya que es el identificador único para un documento, pero_id
no se incluirá en un índice secundario a menos que se agregue explícitamente.Las métricas
totalDocsExamined
ytotalKeysExamined
en losexplain()
resultados mostrarán cuántos documentos y claves de índice se examinaron:Esta consulta se puede mejorar usando la proyección para excluir el
_id
campo y lograr una consulta cubierta usando solo el{a:1}
índice. La consulta cubierta ya no necesita recuperar un documento de ~ 10 MB en la memoria, por lo que será eficiente tanto en el uso de la red como de la memoria:Esto no se puede responder sin el contexto de una consulta específica, un documento de ejemplo y el resultado de la explicación completa. Sin embargo, puede ejecutar algunos puntos de referencia en su propio entorno para la misma consulta con y sin proyección para comparar el resultado. Si su proyección agrega una sobrecarga significativa al tiempo general de ejecución de la consulta (procesamiento y transferencia de resultados), esto puede ser una fuerte pista de que su modelo de datos podría mejorarse.
Si no está claro por qué una consulta es lenta, sería mejor publicar una nueva pregunta con detalles específicos para investigar.
fuente
Con una proyección, puede lograr una situación en la que el conjunto de resultados proviene directamente del índice.
Si tiene un índice compuesto
{x:1, y:1, z:1}
donde ninguno de x, y, z es _id, debe proyectar{_id:0, x:1, y:1, z:1}
porque_id
siempre se devuelve como parte del conjunto de resultados (cuando no se proyecta) y el motor necesita leer archivos de datos para obtenerlo. Esto se debe a que el índice no tiene el valor _id, solo apunta a ese documento donde se almacena el valor.fuente
_id
de la respuesta devuelta, ¿encaja eso en la RAM? ¿Eso ayuda?_id:0
, el resultado se devuelve completamente desde la RAM, sin leer los datos del disco.