Bases de datos clave-valor

He estado leyendo sobre las bases de datos de clave-valor (key-value) como SimpleDB de Amazon, o BigTable de Google, además de otros como CouchDB, Tokyo Cabinet o LightCloud, porque prometen un rendimiento excelente para volumenes de datos muy grandes (pero que muy grandes), a cambio, eso si, de ser muy simples y renunciar a funcionalidades que tenemos en otros sistemas como verificación intrinseca de la integridad de datos, referencias externas (foreign keys) o triggers.

Todo se deja a la aplicación, siendo la base de datos, simplemente donde guardamos los datos. No se verifican integridades, no se comprueban referencias cruzadas, todo eso se ha de implementar a nivel de aplicación, de código cliente.

En un sistema relacional tenemos bases de datos y dentro de cada base de datos tenemos tablas formadas por filas y columnas. En un sistema clave-valor tenemos contenedores, también se les llama cabinets, en cada contenedor podemos tener tantas parejas de clave-valor como queramos, hay sistemas que permiten tener claves duplicadas y hay que no, o que se puede indicar que no queremos que se dupliquen. En cada contenedor podemos tener datos de la misma naturaleza (por ejemplo productos, pedidos, clientes, etc) o totalmente diferente (podríamos tener un contenedor por cliente), eso depende de nosotros, de la aplicación.

A cada clave se asocia un valor (clave=valor), por ejemplo: “Nombre=Jose”, “Apellido=Hernandis”. Pero claro, eso no tiene mucho potencial, si queremos añadir otra persona, ¿cómo lo hacemos? El truco está en la “clave”.

Vamos a suponer que estamos montando un sistema que requiere de identificación de usuarios, vamos a suponer que tenemos un contenedor para los usuarios y otro para los datos de estos (nombre completo, email, fecha nacimiento, etc.). Podríamos hacer que en el primer contenedor la clave fuera el nombre de usuario y el valor la contraseña, así (esto es una versión simplificada):

[users.cab]

pepe=patata
juan=minino
mario=ferrari

En otro contenedor podríamos tener los datos de los usuarios:

[user_data.cab]

pepe_nombre=Jose Alberto
pepe_email=ja@ja.com
pepe_fecha=19700315
juan_nombre=Juan Antoni
juan_email=juan@hatmail.com
juan_fecha=19800218
mario_nombre=Mario Garcia
mario_email=mgarcia@micorreo.es

Esto es una versión simplificada, hay bases de datos clave-valor más sofisticadas, llamadas orientadas a documentos, como CouchDB. Otras permiten estructuras más complejas como almacenar arrays asociados a una clave. Incluso “simular” tablas con sus columnas.

Como se ve la clave se forma por el usuario+dato (usuario_dato), de esa forma, al loguearse un usuario podemos preguntar al primer contenedor que nos devuelva la contraseña del usuario, si no devuelve nada el usuario no existe, si devuelve algo verificamos la contraseña y si es correcta podemos recuperar el resto de valores.

Una alternativa sería en el contenedor user.cab poner el usuario y un ID único, tipo un GUID y utilizar ese GUID para poner la clave a los valores del segundo contenedor.

Hay sistemas que permiten utilizar comodines a la hora de recuperar valores, por ejemplo se puede pedir que devuelva una lista con las claves que coincidan con juan_* de forma que recuperemos juan_nombre, juan_email y juan_fecha. Como se puede ver, del usuario mario no tenemos fecha de nacimiento, si dicho usuario no la ha proporcionado, no tenemos porque almacenarla.

En algunos sistemas los valores se guardan siempre como cadenas, en otros los valores están tipificados: cadena, entero, flotante, fecha, etc.

Las bases de datos clave-valor no están pensadas para el análisis de datos, sino para el almacenamiento puro y duro. Si necesitamos analizar los datos almacenados así, mejor que los pasemos primero a un sistema relacional o, mejor todavía, a un OLAP.

Esto mismo se puede implementar en una base de datos relacional, de hecho es algo que se viene haciendo desde hace años, básicamente para guardar configuraciones. Se trata de utilizar un diseño vertical en lugar de horizontal, me explico:

Horizontal:

ID Usuario Nombre EMail Fecha
1 pepe Jose Alberto ja@ja.com 02/04/1971
2 juan Juan Antonio juan@hatmail.com 18/02/1982
3 mario Mario Garcia mgarcia@micorreo.es null

Vertical:

Se requieren dos tablas para esta variante, al igual que se requerían dos contenedores para el sistema clave-valor.

Usuarios

ID Usuario
1 pepe
2 juan
3 mario

DatosUsuarios

IDusuario Clave Valor
1 nombre Jose Alberto
1 email ja@ja.com
1 fecha 19710402
2 nombre Juan Antonio
2 email juan@hatmail.com
2 fecha 19820218
3 nombre Mario Garcia
3 email mgarcia@micorreo.es

Cada uno de los modelos tiene su pros y sus contras: El horizontal es más sencillo de entender, es más habitual, pero más dificil si crece o se requieren cambios de estructura. El vertical se complica un poco, requiere de unas conversiones de tipos de datos puesto que todo se almacena como cadena o no es sencillo hacer consultas que devuelvan los datos en formato tabla, pero a cambio tenemos unas ventajas como que no es preciso que todos los usuarios tengan los mismos datos, que es inmediato añadir o eliminar datos sin necesidad de reestructurar la tabla, o que cada tabla podría estar en un servidor diferente.

Una lista de los diversos sistemas de bases de datos clave-valor: Anti-RDBMS

2 pensamientos sobre “Bases de datos clave-valor