#2 Batalla de gallos: MongoDB vs MySQL

Seguimos con una nueva batalla, en este caso MongoDB vs MySQL. Vamos a ver que motor de persistencia es mejor y de entre las características de ambos cual ganará esta batalla de gallos.

Las bases de datos relacionales han sido el pilar de un montón de aplicaciones empresariales durante mucho tiempo y mas desde que se lanzó MySQL en 1995, esta ha sido la opción mas popular.

Ahora, sin embargo con la explosión de la minería de datos y el trabajo con grandes volúmenes de estos ha provocado que tecnologías en el campo de bases de datos no-relaciones hayan aparecido en el juego como requisito para el nuevo tipo de aplicaciones.

Así pues, bases de datos no-relaciones como MongoDB se utiliza para este tipo de aplicaciones, aumentando o reemplazando la infraestructura típica relacional.

¿Qué es MySQL?

MySQL es un Sistema de Gestión de Base de Datos (SGDB) Open-Source basado en entidades y relaciones. Si alguien no sabe que es el Open-Source no es nada mas y nada mas que código abierto, distribuido y desarrollado libremente. Cualquiera puede leer, utilizar y contribuir al código fuente de una aplicación Open-Source.

Pues bien, pese a ser software Open-Source, MySQL es mantenido y distribuido por Oracle pero si te apetece ver el código fuente de MySQL puedes forkearte algún repositorio de todos los que tienen en su cuenta de GitHub y echar un vistazo.

Tal y como hacen otros sistema de gestión de bases de datos, MySQL almacena los datos en tablas y estructuras utilizando un lenguaje específico para relacionarse y comunicarse con esos datos guardados. Este lenguaje se llama SQL (Structured Query Language). Como no es nada nuevo no voy a contar como utilizar SQL  sino que voy a dejar este tutorial de la W3SCHOOLS por si alguien viene de nuevas y si quiere conocer  además en qué se basa SQL, cual es el trasfondo técnico de cómo funciona, te diré que se trata del álgebra relacional, aquí tienes un paper introductorio sobre el cálculo y el álgebra relacional.

En diferentes trabajos (técnicos) que he tenido, he visto utilizar SQL no solo a informáticos sino también a gente de contabilidad y finanzas incluso al personal de marketing así que no es una mala idea que tengas unos mínimos conocimientos por si trabajas de forma directa o indirecta con ordenadores y volúmenes de datos.

En MySQL se definen tanto la estructura de la base de datos como las relaciones entre las diferentes entidades que van a existir según tus requerimientos dentro de un universo concreto de datos.

Si te cuesta visualizar la afirmación anterior o no la entiendes lo vas a ver muy claro con el siguiente ejemplo. Yo no sé si serás usuario de Netflix o no pero te voy a contar como funciona. La cuenta mas avanzada (y cara) del servicio de televisión bajo demanda permite mediante un único registro, un único email y una única cuenta bancaria o cuenta de Paypal ser utilizado hasta por cuatro personas diferentes.

Cuatro personas que van a acceder a la plataforma con sus propios dispositivos y que van a necesitar una cuenta de usuario para poder entrar. Si nos planteamos guardar este conjunto de datos podríamos hacerlo tal que así de una manera muy muy muy simplificada y sin tener en cuenta otras entidades y relaciones.

Relación de ejemplo en una base de datos relacionales como MySQL
Relación de ejemplo en una base de datos relacionales como MySQL

Como vemos aquí, tenemos la tabla de Usuario en la que almacenaremos datos relacionados sobre los usuarios, ¿lógico no? Un identificador que será un número único, el nombre de usuario, su email y su contraseña. Por otro lado tenemos la tabla Dispositivo en la que también tenemos un identificador, el tipo de dispositivo, su modelo y una referencia al usuario al que pertenece.

Tenemos así una relación, una relación 1:N en este caso, me explico.

Supongamos que el Rey de España es un viciado de las series y en un momento dado se hace una cuenta en Netflix. Al poco tiempo su mujer, la Infanta Cristina y Urdangarin se enteran y le solicitan un acceso a Felipe.

El Rey se conecta a la plataforma mediante su Mac Air, su mujer con un iPad, la infanta lo hace mediante su smartphone y Urdangarin desde una Smart TV. Así pues el conjunto de datos quedaría tal que así:

Vemos que el identificador de Usuario en la tabla Dispositivo es de 1 relacionándose así con el identificador de Usuario en la tabla Usuario. Con esto tenemos que la cuenta elRey se conecta a Netflix usando un Mac Air, un iPad, un Android y una LG.

Esto es lo que conocemos como bases de datos relacionales.

Aquí te dejo un curso completísimo sobre SQL de la Universidad de Standford.

¿Qué es MongoDB?

MongoDB es una base de datos Open-Source desarrollada por los chicos de MongoDB… y que se guía bajo el concepto de base de datos no relacionales. A diferencia de las bases de datos relacionales que exigían definir estructuras de datos fijas y estáticas que acababan tomando forma de tabla, en las bases de datos no relacionales los datos se guardan en forma de documentos en los que la estructura puede variar.

Así pues en uno de estos documentos podemos guardar  la información de la cuenta de Netflix del Rey junto a sus 4 dispositivos, pero además también podemos meter un conjunto de series y películas que le gusta a cada uno de los 4 dispositivos diferentes.

Y todo eso en un solo objeto.

Este tipo de almacenamiento junto a su forma de acceder y explotar los datos lo conocemos como NoSQL y es super rápido debido a que no tiene que ir a otras tablas a buscar información adicional para darnos una visión parcial o total de un universo de datos sino que cuando consultamos algo, todo lo referente a eso ya lo tenemos.

MongoDB utiliza esquemas de datos dinámicos, lo que significa que se pueden crear registros sin definir la estructura, tales como los campos o los tipos de datos de sus valores. Se puede cambiar la estructura de los documentos simplemente añadiendo nuevos campos o borrando los que ya tenemos.

https://gist.github.com/gorkamu/3305fd3e9977b1eabf2b95becc1b8d20.js

Los documentos no necesitan tener un conjunto idéntico de datos y la desnormalización es el pan de cada día de este tipo de bases de datos. MongoDB se diseñó para tener una alta disponibilidad y una gran escalabilidad por lo que su crecimiento horizontal es mas fácil y barato para los sistemas.

Así pues para consultar la información sobre el Rey de España lo haríamos tal que así:

db.Clientes.find({Nombre:"elRey"});

Accedemos a los datos utilizando JSON para hacer las consultas. Aquí tienes el link a la universidad de MongoDB para aprender mas como funciona este tipo de base de datos no relacional.

Terminología y Conceptos

Con esta tabla vas a ver como muchos conceptos de MySQL tiene su analogía con objetos de MongoDB. Estos son los conceptos típicos de cada sistema.

MySQL MongoDB
Tablas Colecciones
Registros Documentos
Columnas Campos
Joins Documentos embebidos o lincados

 

Comparativa de funcionalidades. MongoDB vs MySQL

Al igual que MySQL, MongoDB ofrece un rico conjunto de características y funcionalidades mucho mas allá de los ofrecidos en simples conjuntos de key-value.  Algunas de las cosas que puede hacer son las consultas Ad Hoc, indexar, hacer balanceo de carga o replicarse.

En la siguiente tabla se pueden ver las funcionalidades de MySQL enfrentadas a las de MongoDB.

MySQL MongoDB
Modelos de datos enriquecidos No Si
Esquemas dinámicos No Si
Datos tipados Si Si
Localidad de los datos No Si
Actualización de campos Si Si
Facilidad para los programadores No Si
Transacciones complejas Si No
Administración y auditoría Si Si
Distribución dinámica de datos No Si

 

Lenguaje de consultas

Ambos sistemas tienen un conjunto diferente de estructuras de lenguaje para poder consultar los datos. En la documentación de MongoDB y en la de MySQL encontraras amplia información para manejarte con estas bases de datos pero para muestra un botón (que asco le he tenido siempre a esta expresión)

Consultas típicas de MySQL

https://gist.github.com/gorkamu/35f6c2da75b6a4d1b286d10da79ca0d3.js

Consultas típicas de MongoDB

https://gist.github.com/gorkamu/4ea507a826703ba144703503523a2094.js

MongoDB vs MySQL: update queries performance
MongoDB vs MySQL: update queries performance

¿Cuándo utilizar MongoDB en lugar de MySQL?

Empresas de diferente tamaño y número de trabajadores están empezando a utilizar este tipo de bases de datos ya que les permite desarrollar aplicaciones mas rápido, manejar datos de muy diferente tipo y administrar aplicaciones de manera mas eficiente a escala.

Al utilizar bases de datos no relacionales como MongoDB eliminas la capa ORM, sistema de mapeo objeto-relacional, que se encarga de convertir los datos guardados en tablas en objetos dentro del código fuente, en Java los POJOs y en PHP los POPOs.

La estructura flexible de una base de datos no relacional significa que el conjunto y tipo de datos pueden crecer y evolucionar sin que afecte a los requerimientos de la capa de negocio.

También, las bases de datos NoSQL se pueden escalar de una manera relativamente sencilla y sin tiempo de inactividad a través de diferentes centros de datos distribuidos, proporcionando nuevos niveles de disponibilidad y accesibilidad en comparación con las bases de datos relacionales.

¿Cuando es mejor opción utilizar una base de datos relacional?

Aunque la mayoría de las aplicaciones modernas requieren un sistema flexible y escalable como MongoDB, hay casos de uso para el que una base de datos relacional sería mas adecuado.

Las aplicaciones que requieren complejas transacciones de datos como el sistema de un banco, en el fondo utilizan bases de datos relacionales, al igual que se dice sobre el COBOL…

Las bases de datos no relacionales no son un sustituto de las bases de datos relacionales, son un complemento que podemos utilizar para diseñar un sistema de respuesta ágil utilizando además Varnish como sistema avanzado de cache.

Volviendo con el ejemplo del banco, podríamos tener una primera capa que manejara datos a través de NoSQL  y que fuera la encargada de interactuar con el usuario y las distintas APIs y una segunda capa utilizando SQL y que se encargase de almacenar los datos bancarios cuando los usuarios hiciesen transferencias.

Entonces… ¿MySQL y MongoDB se pueden utilizar juntos?

Pues como he contado arriba con el ejemplo del banco, si. Pero existen muchísimos ejemplos de desarrollo híbrido. En la gran mayoría de casos se trata mas de saber cual es la herramienta concreta para tus necesidades.

Por ejemplo, muchas de las herramientas de ecommerce utilizan una mezcla de ambas tecnologías. Mostrar un catálogo dinámico de productos que tienen diferentes atributos es un buen ejemplo para usar la flexibilidad en la estructura y en los datos que nos aportan las bases de datos no relacionales.

Por otro lado, el sistema de pago del ecommerce, es probable que utilice bases de datos relacionales como motor de persistencia debido a las operaciones complejas que pueden darse en la lógica de negocio y debido al sistema de transacciones que nos brinda MySQL.

En otros casos, nuevos requisitos en la lógica de negocio empujan a las organizaciones a adoptar tecnologías basadas en MongoDB de cara a la próxima generación de sus aplicaciones internas.

Así pues, con estos ejemplos, es bastante normal pensar que MongoDB es mejor que MySQL debido a su modelo de datos flexible y su arquitectura escalable pero todo es cuestión de valorar las mejores herramientas que se adapten a tus requisitos y no adaptar una solución tan solo porque esta de moda.

 

Y con esto se acabó la segunda batalla de gallos de tecnologías. Deja un comentario o ponme un tweet a través del siguiente banner con las tecnologías que quieres que enfrente en la próxima batalla 😉

[xyz-ips snippet=”FAQS-GORKAMU-TW-YELLOW”]

Hala a mamarla!

Anuncios

#1 Batalla de gallos: Vagrant vs Docker

Desde hace un tiempo a aquí, Vagrant ha sido la solución por defecto para crear entornos de desarrollo que pueden ser fácilmente configurados independientemente de nuestra maquina y compartidos entre el resto del equipo de desarrollo. Existen muchísimos beneficios al utilizar maquinas virtuales frente a tener que instalar todo el software de desarrollo, librerías, dependencias y servidores en nuestra máquina. Los siguientes son un ejemplo de lo que podemos hacer:

  • Construir snippets de código totalmente independiente de la maquina en la que estemos trabajando.
  • Los snippets de código pueden ser compartidos y reproducidos automáticamente con facilidad.
  • Podemos parar y arrancar maquinas virtuales a nuestro antojo.
  • Hostear entornos se convierte en algo efímero y podemos destruir aquellos sitios que no se utilizan ya.
  • Ahorramos tiempo en configuración y ganamos en desarrollo.

Esto ha sido así durante los últimos años, sin embargo, tenemos un chico nuevo en el bloque, un competidor que ha ido ganando terreno poco a poco.

Docker es el chico nuevo y también corre maquinas virtuales pero trabaja de una manera fundamentalmente distinta. En este post quiero hacer una breve explicación sobre cuales son las diferencias entre Vagrant y Docker y sobre cómo instalar WordPress en cada uno de estos.

Si nunca has oído hablar de Vagrant, Docker, máquinas virtuales y entornos de desarrollo te recomiendo que le eches un vistazo a este post en el que hablo sobre Vagrant 😉

Comparación en grandes rasgos de Vagrant y Docker

Para empezar, Vagrant utiliza una arquitectura mucho mas sencilla que la de Docker. Usa maquinas virtuales para correr los entornos independientemente de la maquina anfitrión. Esto se hace utilizando lo que se llama virtualización mediante programas como VirtualBox o VMWare. Cada entorno utiliza su propia maquina virtual y es configurada mediante un fichero que se llama Vagrantfile. Este fichero le dice a Vagrant como tiene que configurar la maquina virtual y que scripts va a necesitar correr junto con su orden de ejecución en el momento de aprovisionar la maquina.

La contrapartida de este enfoque es que cada maquina virtual que creemos contiene no solo el código fuente que estamos desarrollando junto a sus librerías y dependencias sino que además contiene todo un sistema operativo huésped incrementando así en varias Gigas el tamaño de la máquina.

Docker sin embargo utiliza lo que se conoce como contenedores que alojan tu aplicación y todas sus dependencias pero que comparte el kernel (el sistema operativo) con el resto de contenedores.

Estos contenedores se ejecutan como procesos aislados en el sistema operativo anfitrión, pero no están vinculados a ninguna infraestructura especifica. Lo bueno de este enfoque es que los contenedores pueden correr en cualquier ordenador.

¿Cuál es la conclusión de todo esto?

  • Vagrant es mas fácil de entender y es mas sencillo de configurar y poner en marcha. Lo malo es que puede consumir muchos recursos en términos a memoria RAM y almacenamiento.
  • La arquitectura de Docker en cambio es mas compleja de entender y su configuración puede volverse una tortura pero es mucho mas rápido y consume mucha menos CPU y RAM utilizando a su vez menos almacenamiento que Vagrant.
Infografía Docker vs Vagrant
Infografía Docker vs Vagrant

Cómo configurar Vagrant

Una de las mejores cosas sobre ambos sistemas es el ecosistema que se ha creado a su alrededor. Debido al hecho de que los entornos de desarrollo se crean fácilmente con scripts, los desarrolladores de estos scripts los están compartiendo creando así repositorios donde podemos encontrar miles de Vagrant boxes y Docker images diferentes que podemos usar libremente en nuestros proyectos.

Para aprender a configurar Vagrant vamos a utilizar una box de Vagrant que se llama Varying Vagrant Vagrants (VVV) la cual tiene una configuración muy típica para el desarrollo en/de Wordpress.

Antes de empezar necesitarás tener instalado VirtualBox y Vagrant.

Existen varios plugins para configurar Vagrant que VVV recomienda tener instalado:

  • vagrant-hostsupdater: automáticamente actualiza tu fichero de hosts para poder acceder desde el navegador a las maquinas aprovisionadas.
  • vagrant-triggers: permite configurar Vagranta para que dispare scripts cuando utilizamos comandos como vagrant halt o vagrant destroy. Un ejemplo de trigger podría ser el realizar copias de seguridad de la base de datos.

Si ya tienes todos los prerrequisitos instalados vamos a clonar el repositorio de VVV:

$ git clone git://github.com/Varying-Vagrant-Vagrants/VVV.git vagrant-local

Una vez se haya clonado nos dirigimos al directorio para levantar la maquina.

$ cd vagrant-local && vagrant up

Prepárate un café y espera porque el aprovisionamiento de la maquina suele tardar un poquillo… Piensa que necesita descargar todos los ficheros requeridos y configurar el sistema operativo para que podamos empezar a utilizarlo.

Una vez que haya terminado el proceso deberías ser capaz de poder acceder a http://local.wordpress.dev y ver un WordPress nuevo. Personalmente te recomiendo que te leas el README.md de VVV para saber mas sobre cómo configurar y usar sitios en Varying Vagrant Vagrants.

Cómo configurar Docker

Para empezar a configurar Docker y trabajar con el lo primero que necesitas tener instalado es Docker Toolbox que te provee con no solo el cliente de Docker sino que incluso nos trae Docker Machine y Docker Compose, que te ayuda a especificar múltiples configuraciones de contenedores con un solo fichero.

Una vez lo hayas instalado, la primer cosa que tienes que hacer es configurar Docker a través de una de sus maquinaa virtuales. Docker la utiliza para correr el Docker Engine que se encarga de administrar y controlar cualquier contenedor que quieras correr. Para ello vamos a crear una maquina virtual en VirtualBox llamada “docker-vm”.

$ docker-machine create --driver virtualbox docker-vm

Una vez la maquina se haya creado ya podemos comprobar los detalles de la misma ejecutando:

$ docker-machine env docker-vm

Y deberíamos obtener una salida parecida a la siguiente:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/gilbitron/.docker/machine/machines/docker-vm"
export DOCKER_MACHINE_NAME="docker-vm"
# Run this command to configure your shell:
# eval "$(docker-machine env docker-vm)"

Si te has fijado bien, te habrás dado cuenta de que son las variables de entorno del cliente de Docker que utiliza para poder comunicarse con Docker Engine, así que vamos a hacer lo que nos dice y corramos el siguiente comando…

# eval "$(docker-machine env docker-vm)"

Persistiendo la configuración

Cada vez que abras una nueva sesión necesitas volver a correr este comando ya que sus configuraciones no persisten. Para guardar estas configuraciones te recomiendo que añadas el comando al fichero ~/.bashrc de tu sistema. El fichero bash se ejecuta automáticamente cada vez que se inicia sesión en el equipo.

Por fin somos capaces de empezar a crear contenedores de Docker. Una cosa importante a señalar es que Docker corre un proceso por cada contenedor. Esto significa que técnicamente si estamos corriendo una configuración de LAMP (Apache, Mysql y PHP-FPM) todos y cada uno de ellos deberán ser ejecutados en sus propios contenedores.

Esto sin embargo, es solo un ejemplo de guía y en la gran parte de los casos nos será conveniente agrupar procesos en contenedores, por ejemplo, Apache y PHP podrían correr en un contenedor y Mysql en otro diferente.

Afortunadamente existen imágenes oficiales de Docker para el desarrollo en/de WordPress como por ejemplo esta.

El enfoque que vamos a utilizar es precisamente ese, configurar Docker para correr WordPress (incluye Apache y PHP) en un contenedor y Mysql en otro contenedor diferente.

Creando nuestros contenedores

Para crear el contenedor Mysql ejecutamos lo siguiente:

$ docker run --name wordpressdb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress -d mysql:5.7

Podemos echar un vistazo a la documentación de Docker para ver qué es lo que hace cada uno de estos parámetros aunque aquí tienes un pequeño resumen:

  • Con el parámetro –name le estamos dando un nombre a nuestro contenedor, ¿obvio no? Si no lo especificamos se generará un nombre aleatorio.
  • Con el parámetro -e estamos especificando variables de entorno que serán usada por el contenedor. Esta es una forma muy habitual de pasar información al contenedor.
  • Le indicamos al contenedor que se ejecute en modo detached.
  • Finalmente especificamos la imagen del sistema operativo que queremos utilizar con el parámetro image:version. Si esa imagen no existe localmente, Docker la descargará.

Ahora vamos a crear el contenedor para WordPress:

 $ docker run --name wordpress -e WORDPRESS_DB_PASSWORD=password -v "$PWD/":/var/www/html --link wordpressdb:mysql -p 80:80 -d wordpress

Hay dos cosas que hemos utilizado para este contenedor y que no hicimos para el contenedor de la base de datos:

  • Hemos especificado un volumen para mapear nuestro directorio de trabajo contra el directorio /var/www/html de nuestro contenedor utilizando para ello el parámetro -v. Mapeando el directorio podremos editar los ficheros de WordPress.
  • Añadiendo el parámetro –link hemos linkado el contenedor a nuestro contenedor wordpressdb anterior y le hemos dado el alias de mysql. Esto le permite al contenedor de WordPress conectarse contra el contenedor de la base de datos.
  • Hemos configurado el puerto en nuestra maquina virtual.

Podemos comprobar el estado de nuestros contenedores corriendo el siguiente comando:

$ docker ps

Pues ya está, ya serás capaz de visitar la dirección IP de tu maquina de Docker en el navegador y ver la pantalla de instalación de WordPress. Para saber la dirección IP de tu Docker puedes ejecutar el comando:

$ docker-machine env docker-vm

Un buen punto sería añadir un nombre a la IP en tu fichero de hosts para no tener que estar tecleando la dirección IP todo el tiempo.

Bonus: utilizar Docker Compose

Correr comandos tal y como lo hicimos un poquito mas atrás puede ser un coñazo y ademas estar fácilmente expuesto al típico “error humano”. Para ello Docker Compose puede echarnos una mano permitiéndonos utilizar un solo fichero en el que definimos toda la estructura del entorno de desarrollo y luego solo lo ejecutamos con un solo comando, algo así a como trabajan los Vagrantfiles.

Vamos a crear el fichero al que llamaremos docker-compose.yml

wordpress:
  image: wordpress
  environment:
    - WORDPRESS_DB_PASSWORD=password
  ports:
    - "80:80"
  volumes:
    - ./:/var/www/html
  links:
    - wordpressdb:mysql

wordpressdb:
  image: mysql:5.7
  environment:
    - MYSQL_ROOT_PASSWORD=password
    - MYSQL_DATABASE=wordpress

Si te fijas en el fichero, hemos replicado los comandos que hemos utilizado pero en formato yml. Ahora, para correrlo necesitamos ejecutar lo siguiente:

$ docker-compose up -d

En conclusión, ¿cuál es mejor?

Al igual que con el resto de cosas de la vida, no siempre existe un “bueno” y un “malo”, un “correcto” y un “incorrecto”, un “mejor” y un “peor”. Todo depende de cuales son tus necesidades y de cómo lo vas a utilizar así de con cuál te sientes mas cómodo. Personalmente he intentado configurarme un entorno de desarrollo con Docker pero me di cuenta de que era demasiado dificil para las necesidades del desarrollo que estaba haciendo en ese momento. De momento estoy contento con Vagrant ya que es fácil y funciona bastante bien pero estaré atento a ver como madura Docker y ver si lo acabo metiendo en alguno de mis desarrollos 😉

Hala a mamarla!