Skip to content

Comparación Clase Asociación entre SQL y CouchDB. Consulta de datos.

by Cristian Requena on octubre 21st, 2010

En este artículo se realizará la comparación del enfoque de una clase asociación típica entre una base de datos relacional (Oracle, MySQL, SQLServer, etc) y CouchDB, que como sabemos, es NoSQL.

El objetivo, pues, es sencillo: representar en SQL y en CouchDB el diagrama UML mostrado a continuación.

Desde el punto de vista típico de una base de datos SQL se crean 2 tablas de “entidad” (“Clientes” y “Métodos de Pago”) y otra que las “relaciona” (“Métodos de Pago de Clientes”), resultando algo como lo siguiente:

CREATE TABLE clientes (
nif		CHAR(14) NOT NULL,
nombre		CHAR(20) NOT NULL,
apellidos	CHAR(30) NOT NULL,
CONSTRAINT pk_clientes PRIMARY KEY (nif)
);

CREATE TABLE metodos_pago (
id_metodopago	CHAR(2) NOT NULL,
d_metodopago	CHAR(20) NOT NULL,
CONSTRAINT pk_metodos_pago PRIMARY KEY (id_metodopago)
);

CREATE TABLE pago_clientes (
nif		CHAR(14) NOT NULL,
id_metodopago	CHAR(2) NOT NULL,
id_metodo	CHAR(3) NOT NULL,
datos_pago	CHAR(100),
CONSTRAINT pk_pago_clientes PRIMARY KEY (nif, id_metodo_pago, id_metodo),
CONSTRAINT fk_pago_clientes_clientes FOREIGN KEY nif REFERENCES clientes (nif),
CONSTRAINT fk_pago_clientes_pagos FOREIGN KEY id_metodopago REFERENCES metodos_pago (id_metodopago)
);

En resumen: se crean las tres tablas con un conjunto de restricciones, de modo que resultado de introducir valores en el esquema es un set no redundante y normalizado.

Para dar respuesta a esta casuística, en CouchDB hay dos planteamientos típicos: utilizar dos documentos (uno perteneciente a la clase “Clientes” y otro de “Métodos de Pago”, relacionando estos últimos con los primeros mediante un campo) o bien utilizar un solo documento (y, por lo tanto, que dentro de un documento de tipo “Clientes” convivan los datos personales de un cliente y los datos de sus métodos de pago).

La primera posibilidad también es posible llevarla a cabo en una base de datos SQL, a costa de redundar los datos. Esto produce una pérdida de rendimiento, ya que precisamente los esquemas de las bases de datos relacionales requieren, como ya sabemos, de la máxima normalización para ser eficientes.

Por otra parte las restricciones de esquema de las bases de datos relacionales tornan imposible la realización de la segunda opción: requeriría de 999 (la relación entre “Clientes” y “Métodos de Pago” es 1..999) campos adicionales… Impensable.

Veamos la resolución en CouchDB de estos dos casos:

Caso 1: Dos documentos

Uno de los documentos pertenecería a la entidad “Clientes” propiamente dicha, y donde el “_id” del documento sería su NIF para proveer su unicidad:

{
   "_id": "es.nosql.demo.clientes.12346578Z",
   "_rev": "1-a7b1dbc4475bcca028654c46116995f7",
   "tipo": "clientes"
   "nombre": "Perico",
   "apellidos": "Eldel Ospalotes"
}

El otro sería “Métodos de Pago por Clientes”, algo parecido a lo siguiente:

{
   "_id": "es.nosql.demo.metodospagoclientes._id_único",
   "_rev": "1-acb341a7b1dbc4475bcca028654c4611",
   "tipo": "pagoclientes",
   "cliente": "es.nosql.demo.clientes.12346578Z",
   "metodopago": "Paypal",
   "datospago": "blog@nosql.es"
}

Por último será necesario crear un documento de diseño que contenga una vista que relacione los dos documentos anteriores y confeccione un resultado:

{
   "_id": "_design/pagoclientes",
   "_rev": "1-6ae9b200597ec5d4899e904edb6a8aec",
   "language": "javascript",
   "views": {
       "pagoclientes": {
           "map": "function(doc) {if (doc.tipo == 'clientes') {emit([doc._id, 0], doc);} else { if (doc.tipo = 'pagoclientes') {emit([doc._id, 1], doc); } } }"
       }
   }
}

La vista “pagoclientes” devuelve un JSON con dos (o n) filas: la primera contiene el documento de tipo “cliente”, mientras que la segunda (y sucesivas) contiene los datos de pago del cliente.
Este es un comportamiento análogo al que se consigue con las operaciones JOIN en SQL.

Caso 2: Un único documento

Tal y como reza el eslógan de CouchDB: relax. Y ahora veremos por qué.

Como sabemos, CouchDB es una base de datos de documentos, y los almacena como estructuras de datos JSON. Gracias a esto, podemos definir el contenido de un campo como una lista infinita de valores.

Esto significa que el siguiente documento es, sencillamente, factible:

{
   "_id": "es.nosql.demo.clientes.12346578Z",
   "_rev": "1-a7b1dbc4475bcca028654c46116995f7",
   "tipo": "clientes"
   "nombre": "Perico",
   "apellidos": "Eldel Ospalotes",
   "metodospago": [{"tipo": "Paypal", "datospago": "blog@nosql.es"}, {"tipo": "Efectivo"}, {"tipo": "Mastercard", "datospago": "4567-9875-9863-4456/999"}]
}

Después, y en tan sólo una eficiente consulta (ya que los datos se obtienen de forma directa) se podrán obtener los datos.

Esta segunda opción implica, si cabe, aún más replicación de datos, pero debido al eficiente motor de vistas de CouchDB donde por cada vista se mantiene un árbol binario (B+Tree) de búsqueda, esto no implica problemática alguna.

3 Comments
  1. Bien explicado el paradigma de base de datos de esquema libre. Para bases de datos orientadas a documento, como CouchDB, MongoDB, RavenDB u OrientDB, este es su modelo. La ventaja es su flexibilidad y la escalabilidad horizontal. Este esquema no obliga a tener el mismo número de columnas, ni el mismo tipo por columna, lo cual es flexible según el documento que se desee almacenar (a veces más, a veces menos información), y debido a que el esquema de un documento no es fijo y se puede modificar. La escalabilidad horizontal permite adaptar la información en el futuro, en lugar de tener que hacer encaje de bolillos con las relaciones fuertemente atadas a un RDBMS. Un modelo de datos es dinámico, y en el futuro puede cambiar: añadir más columnas, nuevas tablas con clave primaria/foránea, etc. El esquema libre permite su adopción y adaptación rápidamente sin romper con lo anterior.

  2. Buena síntesis!

    Me encanta la frase “Un modelo de datos es dinámico y en el futuro puede cambiar”, puede que me adueñe de ella.. 😉

    Un Saludo,

    Cristian.

  3. mark permalink

    Hize todo paso por paso y comprendi, gracias saludos desde colombia

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS