Fecha publicación: 12 jul 2021

MongoDb índices: múltiples campos

Hasta ahora hemos jugado con consultas que filtraban por un sólo campo,...en el mundo real solemos usar filtros más complejos que pueden implicar a varios campos o ordenaciones, veamos como tratar esto con MongoDb.

Manos a la obra

En el vídeo anterior nos quedamos con un sabor agridulce:

  • Por un lado es muy interesante ver como el query planner de MongoDb es capaz de evaluar que índice usar dependiendo de la consulta que lancemos (era capaz de elegir entre usar el índice para la ordenación o usar el de filtrado).
  • Por otro, sería genial si usará los dos índices, oye filtra y ordena... ¿Cómo podemos hacer esto? con índices compuestos.

Vamos a crear un índice compuesto por year y title

db.movies.createIndex({ year: 1, title: 1 });

Si ahora ejecutamos la consulta podemos ver que este índice permite mejorar tanto el filtrado como la ordenación.

Veamos esto paso a paso, seguimos con nuestra colección de películas, pero para partir de un corte limpio borramos los índices de la colección movies:

db.movies.dropIndexes()

Vamos a tirar una consulta que filtre por año (year) y duración de una película (runtime).

db.movies.find({ year: 2010, runtime: 180 });

Si evaluamos los resultados, obtenemos lo que esperábamos, tiene que recorrer la colección entera (23530 documentos) para devolver 2 documentos.

múltiples campos, sin índice, collscan

¿Qué pasaría si tuviéramos un índice en el campo año? ¿Sería capaz de aplicarlo aunque tengamos múltiples parámetros de filtrado?

db.movies.createIndex({ year: 1 });

Volvemos a lanzar la consulta

db.movies.find({ year: 2010, runtime: 180 });

Y obtenemos una mejora, en vez de tener que recorrer los 23530 documentos, ha sido capaz de aplicar el filtro de año y sólo ha tenido que recorrer las 970 películas de ese año.

múltiples campos, un índice por año

No esta mal, aunque hay margen de mejora, podemos probar a crear un índice sobre el campo runtime y ver que pasa:

db.movies.createIndex({ runtime: 1 });

Volvemos a lanzar la consulta

db.movies.find({ year: 2010, runtime: 180 });

Y fíjate que curioso, en este caso ha descartado el índice por año y el planificador de consultas ha decidido tirar del índice por el campo runtime, bajamos de tener que recorrer 970 películas a 56 películas:

múltiples campos, dos índices año y runtime

Esto nos dejado a medias, hemos mejorado el tiempo de respuesta de la consulta, pero por otro sólo estamos usando un índice, y tampoco tenemos unos tiempos óptimos, ¿qué podemos hacer si esta consulta es crítica y queremos que vaya como un tiro? ¡Crear un índice compuesto por varios campos!

db.movies.createIndex({ year: 1, runtime: 1 });

Si ahora lanzamos la consulta

db.movies.find({ year: 2010, runtime: 180 });

Podemos comprobar que el planificador de consultas elige este nuevo índice, y va al grano, sólo tiene que recorrer 2 documentos.

multiples campos, indice compuesto

¿Con ganas de aprender Backend?

En Lemoncode impartimos un Bootcamp Backend Online, centrado en stack node y stack .net, en él encontrarás todos los recursos necesarios: clases de los mejores profesionales del sector, tutorías en cuanto las necesites y ejercicios para desarrollar lo aprendido en los distintos módulos. Si quieres saber más puedes pinchar aquí para más información sobre este Bootcamp Backend.