Lenguajes preferidos: PHP, MySQL, Perl, AJAX, JavaScript, HTML, XML, Android, Java, RADIUS, HTML5, CSS3, Node.JS
sábado, 29 de septiembre de 2012
El concepto NoSQL
A estas alturas es extraño toparse con alguien que no haya oído hablar de NoSQL, ni que sea de pasada. No obstante, no todos los desarrolladores con los que trato habitualmente tienen claro el por qué de su popularidad, posiblemente debido a que no han tenido aún la oportunidad de trabajar con alguno de los sistemas que se basan en este concepto.
En la carrera de informática, muchos hemos aprendido que los sistemas de bases de datos se clasifican mayormente en tres tipos: Las bases de datos relacionales, las orientadas a objetos, y las relacionales orientadas a objetos. Sin embargo, pronto nos dimos cuenta que, en la práctica, la mayoría de los motores de bases de datos más populares se basan en la arquitectura relacional, y todos ellos utilizan el lenguaje de consultas SQL (con variaciones) para operar con los datos. Tanto es así, que SQL se convirtió con el paso de los años en un estándar “de facto”, debido a su uso.
¿Por qué aparecen los sistemas NoSQL?
Las bases de datos relacionales no tienen nada de malo: Precisamente gracias al transcurso de los años, hemos logrado aprender técnicas bastante comunes para normalizarlas en la medida de lo posible, escalarlas según crece la demanda, y utilizarlas como sistema de persistencia para almacenar información desde nuestro lenguaje procedural u orientado a objetos favorito (entre otros). La cuota de uso de software como SQLite, MySQL, PostgreSQL u Oracle, por poner cuatro ejemplos conocidos, es muy alta, encontrándose en la mayor parte de los desarrollos modernos.
Pero llegó la web, el software como servicio, los servicios en la nube y las startups de éxito con millones de usuarios. Y con todo ello llegaron los problemas de alta escalabilidad. Si bien los modelos relacionales se pueden adaptar para hacerlos escalar incluso en los entornos más difíciles, sí que es cierto que, a menudo, se hacen cada vez menos intuitivos a medida que aumenta la complejidad. Triples y cuádruples JOINs en consultas SQL que asustan al más pintado nada más verlas, a veces poco eficientes, y sistemas de almacenamiento de resultados en cachés para acelerar la resolución de las peticiones y evitar ejecutar cada vez estas pesadas operaciones, son el pan de cada día en muchos de estos proyectos de software.
Los sistemas NoSQL intentan atacar este problema proponiendo una estructura de almacenamiento más versátil, aunque sea a costa de perder ciertas funcionalidades como las transacciones que engloban operaciones en más de una colección de datos, o la incapacidad de ejecutar el producto cartesiano de dos tablas (también llamado JOIN) teniendo que recurrir a la desnormalización de datos.
Algunas implementaciones bien conocidas que podríamos como NoSQL son: CouchDB, MongoDB, RavenDB, Neo4j, Cassandra, BigTable, Dynamo, Riak, Hadoop, y otras muchas.
Pero, ¿en qué se diferencian exactamente?
Si tuvieramos que resumir las características comunes en estos sistemas, yo diría que son principalmente tres: Ausencia de esquema en los registros de datos, escalabilidad horizontal sencilla, y velocidad endiablada (aunque esto último no siempre es cierto, pues muchos de estos sistemas aún no están suficientemente maduros).
La primera característica significa que los datos no tienen una definición de atributos fija, es decir: Cada registro (o documento, como se les suele llamar en estos casos) puede contener una información con diferente forma cada vez, pudiendo así almacenar sólo los atributos que interesen en cada uno de ellos, facilitando el polimorfismo de datos bajo una misma colección de información. También se pueden almacenar estructuras de datos complejas en un sólo documento, como por ejemplo almacenar la información sobre una publicación de un blog (título, cuerpo de texto, autor, etc) junto a los comentarios y etiquetas vertidos sobre el mismo, todo en un único registro. Hacerlo así aumenta la claridad (al tener todos los datos relacionados en un mismo bloque de información) y el rendimiento (no hay que hacer un JOIN para obtener los datos relacionados, pues éstos se encuentran directamente en el mismo documento).
Con escalabilidad horizontal me refiero a la posibilidad de aumentar el rendimiento del sistema simplemente añadiendo más nodos, sin necesidad en muchos casos de realizar ninguna otra operación más que indicar al sistema cuáles son los nodos disponibles. Muchos sistemas NoSQL permiten utilizar consultas del tipo Map-Reduce, las cuales pueden ejecutarse en todos los nodos a la vez (cada uno operando sobre una porción de los datos) y reunir luego los resultados antes de devolverlos al cliente. La gran mayoría permiten también indicar otras cosas como el número de réplicas en que se hará una operación de escritura, para garantizar la disponibilidad. Y gracias al sharding y a no tener que replicar todos los datos en cada uno de los nodos, la información que se mueve entre las distintas instancias del motor de base de datos no tiene por qué ser demasiado intensiva. Por supuesto, seguiremos encontrándonos con problemas de escalabilidad inherentes al tipo de software que estemos construyendo, pero seguramente podamos resolverlos más fácilmente con la ayuda de estas características.
Por último, muchos de estos sistemas realizan operaciones directamente en memoria, y sólo vuelcan los datos a disco cada cierto tiempo. Esto permite que las operaciones de escritura sean realmente rápidas. Por supuesto, trabajar de este modo puede sacrificar fácilmente la durabilidad de los datos, y en caso de cuelgue o apagón se podrían perder operaciones de escritura o perder la consistencia. Normalmente, esto lo resuelven permitiendo que una operación de escritura haya de realizarse en más de un nodo antes de darla por válida, o disminuyendo el tiempo entre volcado y volcado de datos a disco. Pero claro, aún así, existe ese riesgo.
Entonces, no es la panacea
Desde luego que no. Ninguna herramienta de software lo es. Pero sí es cierto que en determinados entornos donde hemos de escalar rápidamente, es una solución muy buena, en especial por el altísimo rendimiento que ofrecen. No en vano, hoy en día se utilizan ya muchísimo no sólo como almacenamiento primario, sino también como sistema de persistencia para guardar cachés, analíticas de uso, y otros datos para los que lo primordial es la velocidad.
En la carrera de informática, muchos hemos aprendido que los sistemas de bases de datos se clasifican mayormente en tres tipos: Las bases de datos relacionales, las orientadas a objetos, y las relacionales orientadas a objetos. Sin embargo, pronto nos dimos cuenta que, en la práctica, la mayoría de los motores de bases de datos más populares se basan en la arquitectura relacional, y todos ellos utilizan el lenguaje de consultas SQL (con variaciones) para operar con los datos. Tanto es así, que SQL se convirtió con el paso de los años en un estándar “de facto”, debido a su uso.
¿Por qué aparecen los sistemas NoSQL?
Las bases de datos relacionales no tienen nada de malo: Precisamente gracias al transcurso de los años, hemos logrado aprender técnicas bastante comunes para normalizarlas en la medida de lo posible, escalarlas según crece la demanda, y utilizarlas como sistema de persistencia para almacenar información desde nuestro lenguaje procedural u orientado a objetos favorito (entre otros). La cuota de uso de software como SQLite, MySQL, PostgreSQL u Oracle, por poner cuatro ejemplos conocidos, es muy alta, encontrándose en la mayor parte de los desarrollos modernos.
Pero llegó la web, el software como servicio, los servicios en la nube y las startups de éxito con millones de usuarios. Y con todo ello llegaron los problemas de alta escalabilidad. Si bien los modelos relacionales se pueden adaptar para hacerlos escalar incluso en los entornos más difíciles, sí que es cierto que, a menudo, se hacen cada vez menos intuitivos a medida que aumenta la complejidad. Triples y cuádruples JOINs en consultas SQL que asustan al más pintado nada más verlas, a veces poco eficientes, y sistemas de almacenamiento de resultados en cachés para acelerar la resolución de las peticiones y evitar ejecutar cada vez estas pesadas operaciones, son el pan de cada día en muchos de estos proyectos de software.
Los sistemas NoSQL intentan atacar este problema proponiendo una estructura de almacenamiento más versátil, aunque sea a costa de perder ciertas funcionalidades como las transacciones que engloban operaciones en más de una colección de datos, o la incapacidad de ejecutar el producto cartesiano de dos tablas (también llamado JOIN) teniendo que recurrir a la desnormalización de datos.
Algunas implementaciones bien conocidas que podríamos como NoSQL son: CouchDB, MongoDB, RavenDB, Neo4j, Cassandra, BigTable, Dynamo, Riak, Hadoop, y otras muchas.
Pero, ¿en qué se diferencian exactamente?
Si tuvieramos que resumir las características comunes en estos sistemas, yo diría que son principalmente tres: Ausencia de esquema en los registros de datos, escalabilidad horizontal sencilla, y velocidad endiablada (aunque esto último no siempre es cierto, pues muchos de estos sistemas aún no están suficientemente maduros).
La primera característica significa que los datos no tienen una definición de atributos fija, es decir: Cada registro (o documento, como se les suele llamar en estos casos) puede contener una información con diferente forma cada vez, pudiendo así almacenar sólo los atributos que interesen en cada uno de ellos, facilitando el polimorfismo de datos bajo una misma colección de información. También se pueden almacenar estructuras de datos complejas en un sólo documento, como por ejemplo almacenar la información sobre una publicación de un blog (título, cuerpo de texto, autor, etc) junto a los comentarios y etiquetas vertidos sobre el mismo, todo en un único registro. Hacerlo así aumenta la claridad (al tener todos los datos relacionados en un mismo bloque de información) y el rendimiento (no hay que hacer un JOIN para obtener los datos relacionados, pues éstos se encuentran directamente en el mismo documento).
Con escalabilidad horizontal me refiero a la posibilidad de aumentar el rendimiento del sistema simplemente añadiendo más nodos, sin necesidad en muchos casos de realizar ninguna otra operación más que indicar al sistema cuáles son los nodos disponibles. Muchos sistemas NoSQL permiten utilizar consultas del tipo Map-Reduce, las cuales pueden ejecutarse en todos los nodos a la vez (cada uno operando sobre una porción de los datos) y reunir luego los resultados antes de devolverlos al cliente. La gran mayoría permiten también indicar otras cosas como el número de réplicas en que se hará una operación de escritura, para garantizar la disponibilidad. Y gracias al sharding y a no tener que replicar todos los datos en cada uno de los nodos, la información que se mueve entre las distintas instancias del motor de base de datos no tiene por qué ser demasiado intensiva. Por supuesto, seguiremos encontrándonos con problemas de escalabilidad inherentes al tipo de software que estemos construyendo, pero seguramente podamos resolverlos más fácilmente con la ayuda de estas características.
Por último, muchos de estos sistemas realizan operaciones directamente en memoria, y sólo vuelcan los datos a disco cada cierto tiempo. Esto permite que las operaciones de escritura sean realmente rápidas. Por supuesto, trabajar de este modo puede sacrificar fácilmente la durabilidad de los datos, y en caso de cuelgue o apagón se podrían perder operaciones de escritura o perder la consistencia. Normalmente, esto lo resuelven permitiendo que una operación de escritura haya de realizarse en más de un nodo antes de darla por válida, o disminuyendo el tiempo entre volcado y volcado de datos a disco. Pero claro, aún así, existe ese riesgo.
Entonces, no es la panacea
Desde luego que no. Ninguna herramienta de software lo es. Pero sí es cierto que en determinados entornos donde hemos de escalar rápidamente, es una solución muy buena, en especial por el altísimo rendimiento que ofrecen. No en vano, hoy en día se utilizan ya muchísimo no sólo como almacenamiento primario, sino también como sistema de persistencia para guardar cachés, analíticas de uso, y otros datos para los que lo primordial es la velocidad.