lunes, 29 de noviembre de 2010

MongoDB: El buen uso de los índices

Los índices son referencias a los documentos Mongo, ordenados de forma eficiente por una clave o campo. Estas referencias están almacenadas en una estructura de árbol, permitiendo una búsqueda rápida y eficiente. Los índices son uno de los recursos más estimados en MongoDB, y saber aprovechar su capacidad nos permitirá optimizar el acceso a los datos. Pero también es un arma de doble filo, que puede darnos problemas si no se sabe utilizar correctamente.

Básicamente, se aplican dos reglas básicas a la hora de aplicar un índice:
- A claves o campos por los que se suele realizar búsquedas.
- A claves o campos que suelene ser ordenados.

CASOS

Vamos a ver algunos casos sobre el uso adecuado de índices. Los ejemplos toman en consideración una colección llamada "col", donde los documentos tienen las claves x e y, y el índice (salvo que se indique otra cosa) está construído sobre x.

Caso 1: Usar db.col.find({$where:"this.x==this.y"})
Los índices no pueden usarse en consultas tipo $where. Sin embargo, en consultas de tipo non-$where, es eficiente usar índices sobre los elementos non-$where.

Caso 2: Rangos usando db.col.find({x:/a/}
La letra 'a' puede aparecer en cualquier parte del campo, por lo que no es eficiente para la ordenación. Sin embargo, sí sería interesante si x es una cadena o x es la expresión irregular /a/.

Caso 3: Actualización usando db.col.update({x:2}, {$inc:{x:3}})
Esta operación no está disponible en versiones antiguas de MongoDB.

Caso 4: Ordenación rápida usando db.col.find({y:1}).sort({x:1})
El índice asegura la ordenación, pero realizado aquí no es el mejor índice.

Caso 5: Campos perdidos usando db.col.find({x:{$exists:true}})
Actualmente no se usa el índice. En versiones futuras de Mongo será tenido en cuenta.

Caso 6: Búsqueda en arrays usando db.col.find({x:{$all:[2,10]}}) teniendo en cuenta que x es un array con los valores [2,10]
El índice realizará búsquedas rápidas en todos los documentos donde coincida el array [2,10].

Caso 7: Índices compuestos usando db.col.find({y:10}).sort({x:1}), con índice compuesto x e y {x:1,y:1}
El índice asegura la ordenación, pero realizado aquí no es el mejor índice.

CREACION DE INDICES
La creación de índices en MongoDB es sencilla. Por defecto, siempre se crea un índice, de forma automática, sobre la clave _id de los documentos de una colección.

Para crear un índice sobre otras claves, usar el siguiente comando:
db.col.ensureIndex({x:1})

El índice puede ser creado en cualquier momento. Si la colección tiene muchos documentos, esta operación puede tardar mucho, bloqueando otras operaciones. Para evitar ésto, se puede indicar que el índice se cree en background (en segundo plano):

db.col.ensureIndex({x:1},{background:true})

Un índice único asegura que los datos de una clave no se repitan (unicidad) y además que sean obligatorios (si no se especican valores, éstos se asumen null, y no podrían estar repetidos):

db.col.ensureIndex({x:1},{unique:true})

Si a la hora de crear el índice sobre la colección, ya existieran documentos con clave duplicada, se podría indicar que que se eliminaran los documentos duplicados:

db.col.ensureIndex({x:1},{unique:true, dropDups:true})

En este caso, sólo se mantendría el primer documento creado (en el orden natural).


MANTENIMIENTO DE INDICES
Los siguientes comandos permiten realizar algunas operaciones de mantenimiento con índices:

db.system.indexes.find({ns:'db.col'})
Muestra los índices creados en la colección 'col'.

db.col.dropIndex({x:1})
Elimina de la colección 'col' el índice sobre la clave x.

db.col.dropIndexes()
Elimina de la colección 'col' todos los índices creados.

db.col.reIndex()
Reconstruye todos los índices creados en la colección 'col'.

LIMITES DE LOS INDICES
Una pregunta interesante: ¿hay límites en los índices?:
- Máximo de 40 índices por colección
- No se previenen índices lógicamente equivalentes (por ejemplo, {x:1} y {x:-1})
- Lo índices mejoran las consultas pero que crean inserciones lentas.
- Los índices más específicos ({a:1,b:1,c:1}) pueden ser más útiles que tener que los menos específicos ({a:1} , {b:1}), pero la ordenación de los más específicos puede no ser tan rápida como en los menos específicos.

Cualquier cambio en las claves, requerirá actualizar también los índices.


Fuente consultada: http://www.slideshare.net/mongodb/indexing-with-mongodb