Indices y MongoDB Aggregation Framework Queries


Una de las herramientas más potentes que tenemos para saber si nuestras consultas son óptimas o no es explain(). Su uso es muy sencillo, pues sólo tenemos que añadirlo a las mismas, de esta manera:

Sabemos que explain tiene tres opciones:

  • queryPlanner (default): Devuelve información del plan ejecutado
  • executionStats: Añade información sobre los tiempos de ejecución
  • allPlansExecution: Nos da información de todos los planes, no sólo del ganador

 

La opción por defecto es suficiente para saber si nuestra consulta utiliza algún índice pero, para conocer el tiempo que va a tardar la consulta tenemos que utilizar la opción ‘executionStats’.

 

Pero, ¿esto funciona igual para las consultas que utilizan el aggregation framework? La respuesta es: NO. En estos casos el explain() sólo devuelve la información básica, es decir, la del plan escogido.

 

Vamos a ver algunos ejemplos. Para ello, insertamos 10.000 documentos:

Y ejecutamos un consulta de aggregación utilizando explain(), esta por ejemplo:

En la salida que nos devuelve vemos que el plan ganador no utiliza ningún índice, sino que hace un barrido de toda la colección.

 

¿Qué pasa si añadimos un índice y lanzamos la misma consulta? Vamos a verlo:

Comprobamos que para esta consulta el resultado es el mismo pues estamos solicitando el agrupamiento de todos los documentos de la colección.

 

Entonces, ¿qué tenemos que hacer para ser capaces de que nuestra consulta utilice el nuevo índice? Sólo tenemos dos opciones:

  • Añadir un $sort como primer stage
  • Añadir un $match como primer stage

Una vez terminada la ejecución de ese primer paso MongoDB sólo tiene documentos, que serán la entrada al segundo stage, pero ya no tiene referencia de índices. Por lo tanto, nuestra única oportunidad está en ese primer paso y, para ello, sólo podemos utilizar $match o $sort.

 

Lo hacemos:

Hay casos en los que es suficiente con esta información, pero otras veces necesitamos conocer el tiempo que va a tardar nuestra consulta. Ya sabemos que explain() no nos lo va a decir cuando lo utilizamos con el aggregation framework. ¿Qué podemos hacer ante este problema?
Aún tenemos un as guardado en la manga. El truco está en activar el profiling y ejecutar la consulta, así:

Ahora sólo nos queda buscar nuestra consulta en el log:

La información que obtenemos es:

  • base de datos
  • colección
  • consulta
  • planSummary
  • keysExamined
  • docsExamined
  • nreturned
  • tiempo de ejecución

 

No olvidéis dejar el profiling como lo teníais antes:

Espero haberos aportado algo con este post. Como siempre, cualquier comentario será bienvenido. Muchas gracias y hasta otra.

 

 

 

 

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

4 − 4 =