Algunas claves a la hora de diseñar nuestros datos: Schema Design con MySQL vs Schema Design con MongoDB


Think Different WordleEn estos últimos tiempos, se está viendo que hay un emergente mundo y un crecimiento de soluciones de base de datos y yo, como desarrollador, me estoy haciendo muchas preguntas, tales como: ¿Debo usar SQL o NoSQL? ¿cuándo debo usar una u otra? ¿Cuál es la diferencia? ¿Cuál debo utilizar para mi proyecto? ¿Puedo o debería utilizar los dos? son preguntan cuando te cuestionas cosas como: déjalo así “es que esto se ha hecho siempre de esta forma”. Pienso que tenemos la obligación, como desarrolladores, el saber las diferentes posibilidades disponibles para obtener los mejores resultados de nuestros proyectos y esto quedará reflejado en nuestros clientes.

En la mayoría de los proyectos estamos utilizando las bases de datos relacionales como algo implícito en nuestros proyectos, no quiero decir que esté mal, pero tampoco creo que esté bien, si se ha puesto implícitamente una base de datos relacional. Además, el cambio de paradigma y pensamiento a la hora de utilizar soluciones NoSQL como MongoDB, nos trae retos muy interesantes.

Uno de los retos a los que me enfrentado cuando he comenzado a utilizar una base de datos NoSQL, es el diseño del esquema, a pesar que una NoSQL como MongoDB es Schemaless, pero esto no quiere decir que no necesites pensar en un esquema. Pues bien, si mientras que en el mundo relacional, la normalización es desde dónde siempre se arranca la manera de diseñar la funcionalidad de nuestro proyecto, ahora nos tenemos que plantear el ¿cómo debemos diseñar nuestras colecciones y documentos, al crear una nueva aplicación de MongoDB?

Veamos un ejemplo sencillo cómo vamos a crear una estructura de datos para MySQL o cualquier base de datos relacional y para MongoDB. Supongamos que queremos almacenar información de clientes y los detalles de su ubicación:

mysql> select * from custumer;

| id | name | second_name | email……………………..
========================
| 1 | Ana | Fernandez | afernandez@email.com…………………..
| 2 | Luis | Sánchez | lsanchez@email.com……………………
| 3 | Antonio | López | alopez@email.com…………………….

mysql> select * from accounts;

| id | customer_id | number | zip  | country |
========================================
| 10 | 1 | 45 | 28044 | ES
| 11 | 2 | 22 | 28044 |  ES
| 12 | 3 | 34 | 28044 |  ES

Vamos a sacar algunos datos haciendo consultas SQL:

Quiero saber todos los clientes que tenemos en la que únicamente afecta a una única tabla:

SELECT count(*) from customer

Ahora veamos los casos en los que nos afectan varias tablas:

SELECT zip from accounts a join customer c ON a.customer_id = c.id WHERE name = ‘Antonio’

SELECT name FROM customer c LEFT JOIN accounts a ON a.customer_id = c.id WHERE a.id IS NULL

Si estos mismos datos, los queremos pasar a una NoSQL, ¿cómo debemos diseñar nuestras colecciones en MongoDB para que sean más eficientes? Pues si estamos pensando en hacerlo con el uso de la tercera forma normal es posible hacerlo, pero seguramente no sería eficaz el tener JOINS entre documentos, ya que tendríamos que controlar nosotros mediante programación, el asegurar que tengamos integridad en ambos documentos. . Entonces, ¿qué diseños podríamos tener es estos casos?

Una primera buena opción, sería la de fusionar toda la información en la misma colección:

> db.customer.find()
{
_id” : ObjectId(“526403c77c1042777e4dd7f1”), “name” : “Luis”, “second_name” : “Sánchez”, “email” : “lsanchez@email.com”,

}

…………………..

{ “_id” : ObjectId(“526403c77c1042777e4dd7f5”), “name” : “Ana” }

Observa que MongoDB es “schemaless dynamic”, esto significa que no hay ningún problema en el almacenamiento de documentos que no tienen la misma estructura. Pero cuidado con este concepto que no te confunda, ya que la desigualdad debe ser coherente o incoherente, en este caso el que no tenga email o como en otros casos que no tenga tags o comentarios es una desigualdad coherente. El hacerlo de esta forma confunde un poco el hecho de que no queda claro que datos pertenecen a accounts, así que si quieres obtener toda la información de account para Luis, tendrás que entender correctamente la estructura de datos del conjunto. Pero podríamos reorganizarla de tal forma que MongoDB soporta subdocumentos:

{
   _id: ObjectId(“526403c77c1042777e4dd7f1”),
   name: “Carlos Sánchez Pérez”, 

   “email” : “csanchez@email.com”,
    account: {

                street: “c/Mengala”,
                city: “Madrid”,
                Number: “25 3º A”,
                zip: 28044
                }
}

O podríamos hacerlo a la inversa es decir, hacerlo en account incorporar los datos de los clientes, pero de esta forma quedaría un poco confuso ya que tenemos casos en los que algunos no podrían tener información:

> db.account_embed.find()
{
“_id” : ObjectId(“526403c77c1042777e4dd7f1”),
“country” : “ES”,

“customer” : {
“name” : “Luis”
}
}

{
“_id” : ObjectId(“526403c77c18576777e4dd7g1“),
“customer” : {
      “name” : “Alfredo”
     }
}

Según vemos hay demasiadas opciones a las que podemos optar, bien pero ¿Cómo saber elegir? Aquí es donde debemos tener en cuenta una diferencia fundamental entre las bases de datos MongoDB y las bases de datos relacionales, cuando se trata de diseñar nuestro esquema. Las colecciones dentro MongoDB deben ser diseñadas con los patrones de acceso más frecuentes de la aplicación, mientras que en el mundo relacional, hay que olvidarse de cómo se accede a los datos si se trata de normalizar las tablas. Pero si en nuestro caso leemos los datos del cliente en la mayoría de los casos o en el 99% de las veces, el tener 2 colecciones separadas es una buena solución, ya que evitaría tener los datos de account del cliente en la memoria si casi nunca se utiliza.

Pero si la necesidad de nuestra aplicación es mostrar toda la información para un cliente determinado, en ese caso debemos considerar que almacenar toda la información en la misma colección se acerca mucho a la mejor solución.

Conclusión

He intentado poner las diferencias fundamentales entre MySQL y MongoDB cuando se trata de la creación de la estructura de datos adecuada para una aplicación, con lo que si estamos hablando de MongoDB, es necesario conocer el patrón de acceso a los datos, es definitiva lo que nos va a proporcionar el rendimiento de los resultados.

Es muy importante tener esto en cuenta, ya que como la creación de un mal diseño de un esquema, es una receta para el desastre ya que podemos llegar a tener unas consultas complicadas de escribir y de optimizar, será lento y que a veces tendremos que reemplazado por el código para parchearlo y finalmente todo puede conducir a una bajada de rendimiento de nuestra aplicación y frustración para el usuario que la está utilizando.

Por tanto utiliza el sentido común y reflexiona por un momento antes de decantarte por una solución u otra.

Un comentario en “Algunas claves a la hora de diseñar nuestros datos: Schema Design con MySQL vs Schema Design con MongoDB

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s