MongoDB lo que deberías de saber antes de utilizarlo

¿Cuando utilizar Mongodb?

Para poder decidir si usar MongoDB es una opción adecuada, vamos a ver las características de MongoDB, base de datos NoSQL. Evidentemente MongoDB no es la mejor solución para todos los proyectos, sino no sería necesario este artículo. Teniendo claro los puntos fuertes de MongoDB, así como los débiles, tendremos más posibilidades de utilizarla adecuadamente.

Un poco de base de datos NoSql

Hoy en día hay gran cantidad de aplicaciones o servicios en Internet que generan una ingente cantidad de datos, bien de manera automática (logs, lectura de sensores,…) o bien por la interacción con los usuarios (redes sociales, foros, herramientas colaborativas ,…).

Nos encontramos ante un fenómeno, denominado Big Data, en el que la información que se genera es muy grande (Volumen), se hace de manera rápida y constante (Velocidad), y en ocasiones de forma no estructurada y cambiante (Variedad). Durante muchos años los servicios y aplicaciones de Internet se han apoyado en las bases de datos relacionales, que funcionan muy bien con fuentes de información que generan datos muy bien estructurados (no variantes).

Pero pronto se observó que estas bases de datos relacionales tenían ciertas carencias a la hora de enfrentarse a aplicaciones que generan Big Data. El principal problema se presentaba a la hora de mantener el rendimiento conforme aumentaba la cantidad de datos. Es decir, no escalan muy bien a partir de cierto volumen.

En el mundo relacional, en general se escala verticalmente (aumentando recursos de la máquina), pero cuando hay que hacerlo horizontalmente (añadiendo máquinas) pueden aparecer problemas de rendimiento. Cuando nuestra aplicación maneja Big Data, es conveniente escalar horizontalmente, ya que almacenar todos los datos en una máquina se hace difícil. O bien no existe la máquina capaz de manejar todos nuestros datos, o bien es muy cara.

Lo que sucedió es que determinadas organizaciones empezaron a trabajar en nuevas bases de datos pensadas desde el inicio para enfrentarse a este tipo de información. Estas nuevas bases de datos están diseñadas para trabajar con grandes fuentes de información (Big Data) no estructuradas y/o cambiantes, y para escalar horizontalmente en vez de verticalmente. Pronto a alguien se le ocurrió acuñar un término para agruparlas: NoSQL.

Lo que pasa es que ese término es confuso, ya que da a entender que la principal característica de estas nuevas bases de datos es que no tienen un lenguaje SQL, típico de las bases de datos relacionales, cuando en realidad algunas de ellas si lo tienen. Más adelante se empezó a utilizar la frase Not Only SQL en vez NoSQL a secas, para intentar restar confusión al término. Dentro de las bases de datos NoSQL hay gran variedad, cada una con sus matices y sus diferencias.

¿Cómo maneja MongoDB la variedad?

Veamos cómo almacena la información MongoDB, para poder entender cómo maneja la variedad de ésta. MongoDB plantea un modelo de datos orientado al documento, utilizando BSON como formato de almacenamiento. BSON no es más que JSON codificado de manera binaria. JSON tiene estructuras afines en muchos lenguajes de programación (C, Java, Javascript,…), pero no depende de ninguno de ellos. Esto facilita el desarrollo de aplicaciones.

En MongoDB los documentos se agrupan en colecciones. Podríamos decir que los documentos juegan un papel similar al que juegan los registros en el mundo relacional. Las colecciones son parecidas a las tablas del mundo relacional, aunque no imponen una estructura fija a los documentos que contienen, ni siquiera al tipo de datos de cada campo.

Podríamos decir que en MongoDB la estructura de los datos (bases de datos, colecciones, campos,…), es implícita, flexible y dinámica. Implícita porque lo normal es que los documentos de una colección compartan estructura, y ésta no se declara de manera explícita antes de introducir los documentos. Flexible porque esa estructura no se impone a ningún documento. Y dinámica porque la estructura puede cambiar.

Esto no quiere decir que cuando hagamos una aplicación no tengamos que realizar un proceso de análisis de la información a guardar en MongoDB. Al contrario, hay que hacerlo, aunque de manera diferente a cómo se hace en el mundo relacional (normalización). Por ejemplo, algunos de los aspectos más importantes a la hora de diseñar nuestra estructura de datos en MongoDB son la forma en que se consultan los datos, la forma en que se particionan (si es que particionamos) y los requisitos de atomicidad.

Una vez decidida la estructura de datos que utilizaremos para almacenar una fuente de información, ¿qué sucede si ésta varía? Evidentemente la aplicación que la maneja, y que posteriormente la almacena en MongoDB debe cambiar. Esto es independiente de la base de datos escogida.

Pero en MongoDB no tenemos que crear ni modificar colecciones (tablas). Podemos almacenar los nuevos documentos, posiblemente con una estructura distinta a los anteriores, en la misma colección, o en una nueva. En el primer caso no tenemos que modificar la estructura de la colección, puesto que ésta no existe. Y en el segundo caso no tenemos que crear la colección, puesto que ésta se crea de manera automática cuando introducimos el primer documento.

Así que MongoDB no va a hacer ningún tipo de comprobación sobre la estructura de un documento, ni sobre la validez o tipo de los campos que lo componen. Sí queremos hacer esto, tendremos que llevarlo a cabo en la propia aplicación. Esta flexibilidad a la hora de trabajar con información que varía, es sobre todo muy útil en las fases iniciales de un proyecto, durante las cuáles las especificaciones cambian a menudo. O cuando trabajamos con información que no cuenta con una estructura fija.

MongoDB tampoco proporciona integridad referencial. Así que si en una colección hacemos referencia a un documento de otra colección, la responsabilidad de comprobar que el documento referenciado existe es de la aplicación, y no de la base de datos como en el mundo relacional.

¿Cómo maneja MongoDB la velocidad?

Si la velocidad con la que se genera o modifica la información almacenada en MongoDB es alta, puede que se presenten problemas a la hora de llevar a cabo estas operaciones. En primer lugar hay que tener en cuenta que durante el tiempo que tarda una operación de escritura (creación, modificación o eliminación) en llevarse a cabo en MongoDB, se bloquea el acceso a toda la base de datos en la que se efectúa la operación.

La idea es hacer que estas operaciones duren el menor tiempo posible, para permitir el mayor número de ellas por segundo, y para que las bases de datos estén el menor tiempo posible bloqueadas. ¿Cómo consigue MongoDB que estas operaciones sean rápidas?

Teniendo en cuenta que en general las operaciones de escritura se ralentizan cuántos más índices tenga una colección, hay que destacar una operación concreta que penaliza el rendimiento de MongoDB, y que hay que tratar de minimizar su frecuencia de ocurrencia. Se trata de las actualizaciones que provocan movimientos.

Cada documento en MongoDB se almacena en lo que podemos denominar cajón (register en inglés). Este cajón contiene el documento y cuenta con un espacio extra para futuros crecimientos del documento. Si una actualización provoca que el documento resultante no quepa en su cajón, hay que cambiarlo de cajón. Esto es lo que se denomina un movimiento, y lo que hay que tratar de minimizar. Si una actualización no requiere de un movimiento, se realiza rápidamente.

También hay que tener en cuenta el particionamiento, método por el cuál se realiza el escalado horizontal en MongoDB. Cuando particionamos una colección, sus documentos se reparten entre las distintas particiones que pertenecen al sistema de particionamiento. Si realizamos el particionamiento teniendo en cuenta nuestras operaciones de escritura, podemos conseguir que éstas se repartan hasta cierto punto entre todas las particiones.

De este modo podemos conseguir que el número total de operaciones de escritura que puede soportar el sistema aumente. Si tenemos operaciones de escritura simultáneas que afectan a particiones distintas, se pueden llevar a cabo en paralelo.

Por otro lado, cabe señalar que las operaciones de escritura en MongoDB se benefician especialmente de la utilización de medios de almacenamiento de estado sólido (SSD), frente al uso de los tradicionales disco duros.

En definitiva, podemos decir que para aplicaciones en las que las operaciones de escritura sean muy intensas MongoDB puede no ser un buen candidato. Podemos crear más bases de datos para minimizar el efecto de los bloqueos, si bien se supone que en versiones futuras esto se va a cambiar por bloqueos a nivel de colección. También podemos crear documentos con campos rellenados de manera artificial, para que cuando sean modificados no crezcan y provoquen movimientos.

En todo caso, posiblemente las mejoras que más solicitan los usuarios de MongoDB tienen que ver con el rendimiento de las operaciones de escritura y el bloqueo a nivel de base de datos.

¿Cómo maneja MongoDB el volumen?

Para mejorar el rendimiento a la hora de manejar grandes cantidades de datos, MongoDB trabaja con la información en memoria, si bien la guarda en los discos duros de las máquinas en las que está funcionando. Es decir, para llevar a cabo una operación, la información afectada en cada caso tiene que estar en memoria (mucho más rápida que un disco duro). Si no está en memoria se copia del disco duro (ó SSD).

De este modo, al trabajar directamente con la memoria las operaciones se llevan a cabo más rápido. Si la parte activa de nuestros datos (la que se utiliza en las operaciones habituales), lo que en MongoDB se conoce como Working Set, cabe en memoria, la gran mayoría de operaciones que realicemos no requerirán copiar información del disco duro a memoria, ya que casi seguro estará en memoria cuando queramos utilizarla. Dichas operaciones se llevarán a cabo con bastante rapidez.

Si la parte activa de nuestra aplicación no cabe en la memoria de nuestro sistema, y un porcentaje importante de las operaciones habituales provocan una copia de datos de disco a memoria, el rendimiento de MongoDB puede verse afectado de manera muy importante.

En las operaciones de escritura el hecho de trabajar directamente con la memoria no es tan ventajoso, puesto que de manera periódica hay que guardar en disco las operaciones que se han llevado a cabo en memoria desde la última vez. El hecho de acceder al disco para hacer varias operaciones de una vez puede proporcionar cierta mejora de rendimiento, pero en cualquier caso la calidad del medio de almacenamiento es el factor limitante cuando se trata de escrituras.

En cuanto al particionamiento, hemos visto anteriormente que puede contribuir a mejorar la capacidad de nuestro sistema para llevar a cabo operaciones de escritura. Pero también puede contribuir a la hora de consultar grandes cantidades de datos.

Si particionamos teniendo en cuenta las operaciones de lectura, podemos conseguir que éstas se repartan entre todas las particiones. De alguna manera es como si pudiésemos utilizar toda la memoria de todas las particiones, aumentando así el tamaño máximo de nuestra parte activa.

Otra forma de mejorar el rendimiento al trabajar con grandes cantidades de datos es mediante el uso de índices. Éstos nos permitirán acelerar las operaciones de consulta de datos. Los índices ocupan menos que las colecciones, y nos permiten trabajar con éstas sin tener que acceder a todos sus documentos. Por ejemplo, para trabajar con una colección de 60 GB de datos, puede que con un índice de 2 GB podamos llevar a cabo el 80% de las consultas de esa colección, evitandonos tener que acceder a los 60GB.

Como los índices perjudican en general el rendimiento de las operaciones de escritura, se hace necesario estudiar la creación de cada uno de ellos, para decidir si ese perjuicio se compensa con el beneficio que aporta en las operaciones de lectura. También habrá que tener en cuenta la importancia relativa de cada tipo de operaciones. Es decir, si hay claramente más operaciones de lectura que de escritura, tendremos menos en cuenta el perjuicio sobre estas últimas. Y viceversa.

Los índices existen en prácticamente todas las bases de datos. No es que MongoDB sea muy distinto a las demás en este aspecto. Si que tiene algunas características destacadas, como la posibilidad de crear índices sobre todo tipo de campos, incluidos los que almacenan arrays o datos de geoposicionamiento.

En cuanto a la posibilidad de realizar operaciones de análisis de datos, MongoDB cuenta con varias alternativas, como una implementación propia de MapReduce, la posibilidad de trabajar con Hadoop, o un potente sistema de agregación propio.

Otras cosas que no tiene MongoDB

Las dos principales características del mundo relacional que no tiene MongoDB, son las transacciones y los joins. Esto se debe a que en MongoDB se considera que su implementación penalizaría su capacidad para escalar bien horizontalmente. Es decir, si MongoDB tuviese estas dos características, conforme aumentásemos el número de particiones el rendimiento iría cayendo.

MongoDB garantiza la atomicidad de las operaciones sólo a nivel de documento, es decir, todas las modificaciones que hagamos sobre un documento en una instrucción son atómicas. Por esto a veces incluir documentos dentro de otros en vez de crear más colecciones, puede contrarrestar el hecho de que MongoDB no soporta transacciones, y también el que no tenga joins. Y es que esta inclusión de documentos en otros, permite que podamos recuperar en una consulta gran cantidad de información, en vez de tener que consultar varias tablas.

Conclusión

Podríamos concluir que las mayores virtudes de MongoDB están en su capacidad para escalar horizontalmente, en el buen rendimiento que ofrece en general en las operaciones de lectura, en su capacidad para adaptarse a los cambios en la estructura de la información, en las posibilidades que ofrecen sus índices, y en la facilidad que ofrece para programar aplicaciones en muy diversos lenguajes.

Sus principales problemas son las características del mundo relacional que no implementa, que por un lado le ayudan en algunas de sus virtudes, pero que en ocasiones hacen que no sea un buen candidato para determinados proyectos que necesitan de esa funcionalidad no implementada. Sobre todo si trabajamos con información eminentemente relacional y que no varía. Y las posibles mermas de rendimiento que pueden tener lugar en aplicaciones en las que las operaciones de escritura sean muy intensas.

Leave A Reply

Tu dirección de correo electrónico no será publicada.