4

Introducción al uso de índices en MongoDB

Como vimos en una de las clases del curso, los índices nos permiten optimizar las consultas que hacemos a nuestra base de datos. De acuerdo a la documentación de MongoDB, los índices son “estructuras de datos especiales que almacenan una pequeña porción de los datos de la colección de tal forma que sea fácil de recorrer. El índice almacena el valor de un campo específico o de un conjunto de campos, ordenados por el valor de dichos campos. El orden de cada una de las entradas del índice permite realizar consultas de igualdad o rango de manera eficiente.

Sin los índices, MongoDB debe hacer un análisis de la colección, es decir, leer todos los documentos en una colección, con el fin de encontrar los documentos que cumplan con los criterios de consulta.

Supongamos que queremos consultar un tema en una enciclopedia, podríamos ir leyendo página por página hasta que encontremos la información que necesitamos, pero nos tardaríamos demasiado tiempo. Ahora bien, si contamos con un índice que nos indique en qué página se encuentra cada tema nos ahorramos mucho más tiempo que revisando cada página; así nos pasa con las consultas de base de datos.

Manos a la obra

Para todos los ejemplos utilizaremos la estructura de la base de datos usada en el curso, y en mi caso trabajaré con más de 1000 documentos en la colección para ver el potencial en las consultas. A medida que vayamos avanzando introduciré conceptos claves y recursos de interés.

Dentro del shell de MongoDB usemos la base de datos cryptongo y hagamos la siguiente consulta:

//Consulta número 1db.tickers.find({id: 'bitcoin'}).explain('executionStats')
Captura de pantalla 2018-09-25 20.12.54.png

En la imagen anterior observamos una porción de los resultados arrojados por la consulta número 1, y es que al agregar el explain(‘executionStats’) obtendremos información relacionada a la ejecución de la consulta. Si prestamos atención a la llave “executionStats” tendremos dos valores importantes:

  • “executionTimeMillis”: tiempo total de la ejecución de la consulta en milisegundos.

  • “totalDocsExamined”: número total de documentos analizados. En el ejemplo anterior, se analizaron los 1200 documentos de la colección para retornar los 12 que coincidieron con el criterio de búsqueda.

Debido a que no tenemos ningún índice sobre el campo id, al hacer esa consulta Mongo busca en todos los documentos de la base de datos, por lo cual deberíamos tener el total de documentos almacenados en la colección como valor del campo “totalDocsExamined”.

Si ahora ejecutamos la siguiente consulta (importante: el _id que se observa a continuación es de uno de mis documentos, pueden sustituirlo con uno que sepan que existe en su base de datos):

//Consulta número 2db.tickers.find({_id:ObjectId('5ba2e0ace34c591d0c9681f9')}).explain('executionStats')
Captura de pantalla 2018-09-25 21.22.15.png

Podemos observar que el valor para “totalDocsExamined” ahora es de tan solo 1 y por consiguiente el “executionTimeMillis” también es menor. Esto se debe a que por defecto MongoDB asigna un índice al campo _id y es más que evidente el poder de los índices.

Para crear un nuevo índice en nuestra colección usaremos el método createIndex() que tiene la siguiente forma:

db.collection.createIndex( <key and index typespecification>, <options> )

Donde key representa un documento con los campos de la colección que queremos indexar, type hace referencia al tipo de índice que queremos crear, y options sirve para indicar con un documento los valores que controlan la creación del índice.

Si quisiéramos crear un índice sencillo en orden descendiente para el campo id y mejorar el desempeño de la última consulta que probamos, hacemos lo siguiente:

db.tickers.createIndex({ id: -1 })
Captura de pantalla 2018-09-25 20.14.43.png

Ahora que tenemos el índice asociado al campo id repetimos la consulta número 2 y obtenemos el siguiente resultado:

Captura de pantalla 2018-09-25 20.18.13.png

Como podemos ver, ahora sólo examinamos los documentos necesarios para obtener los resultados esperados y no toda la colección, lo cual representa una mejora considerable al rendimiento de nuestra aplicación.

En caso de querer ver los índices que tenemos en nuestra colección tickers:

db.tickers.getIndexes()
Captura de pantalla 2018-09-25 20.19.14.png

Luego de hacer el getIndexes() podemos ver que contamos con índices para los campos _id e id, junto con información respectiva de cada uno de ellos.

Por último, para eliminar un índice tenemos el mismo escenario que con las colecciones; podemos eliminar un índice en particular o eliminar todos los índices (menos el del campo _id), así como se muestra a continuación:

//Elimina el índice que creamos anteriormente
db.tickers.dropIndex('id_-1')

//Elimina todos los índices de la colección tickers, exceptuando el del campo _id
db.tickers.dropIndexes()

Tipos de Índice y opciones de creación

Como vimos anteriormente, al momento de crear un índice debemos especificar el tipo y las opciones de creación en base a las necesidades de cada consulta. A continuación se muestran algunos y si quieres profundizar más, puedes consultar la documentación:

  1. Tipos
  • Campo individual: usado para índices de un solo campo donde se facilita el ordenamiento de los documentos.

  • Índice compuesto: permite crear índices sobre varios campos. El orden en el que está definido cada campo tiene importancia.

  • Índice multi-llave: son aplicados a campos que tienen información contenida en arreglos. Al usar estos índices, MongoDB crea una entrada para cada uno de los elementos del arreglo.

  1. Opciones
  • Índices únicos: con la propiedad unique se encarga de no permitir valores repetidos en los campos indexados.

  • Índices parciales: solo mantiene un registro de los documentos que coinciden con las condiciones de filtro suministradas, lo cual permite reducir los requerimientos de memoria.

  • Índices con tiempo total de vida: eliminan automáticamente los documentos de una colección luego de una duración de tiempo especificada.

Consideraciones

  • Agregar un nuevo índice afecta a las operaciones de escritura. Para colecciones que manejan gran número de operaciones de escritura, los índices afectan un poco el rendimiento puesto que con cada inserción de documentos se deben actualizar los índices.

  • Cuando un índice está activo consume espacio en disco y memoria. Este consumo puede ser considerable por lo cual debe ser analizado y estudiado al momento de trabajar con índices.

Conclusiones

Los índices son un recurso de gran utilidad para mejorar el rendimiento de las consultas en nuestras bases de datos. Con este tutorial, tienes una base para profundizar y jugar aún más con el uso de los índices en MongoDB. Espero que les ayude mucho en sus aplicaciones.

A continuación les dejo varios enlaces con información de interés:

Escribe tu comentario
+ 2
1
4Puntos

Oh, great, your article provided me with useful information and a fresh perspective on the subject. Are you a Fall Guys?

0
14805Puntos

Muy buen artículo. Me ha servido para entender mejor el funcionamiento de los índices.