Datomic, una base de datos diferente

datomic-logo-medium

Hasta hace no mucho tiempo, siempre que uno pensaba en bases de datos lo hacía en bases de datos relacionales. Podía ser Oracle, SQL Server, MySQL o cualquier otra pero, en definitiva, todas bases de datos relacionales y basadas en SQL.

Sin embargo, de unos años a esta parte se ha ido extendiendo el uso de bases de datos «alternativas» como MongoDB, DynamoDB, Cassandra o RavenDB. Estas bases de datos están basadas en otros paradigmas (documentos, columnas, clave-valor) y tienen características que las hacen especialmente adecuadas para determinados escenarios.

Una de las bases de datos NoSQL que más me ha llamado la atención últimamente (junto con neo4j, una base de datos orientada a grafos) ha sido Datomic.

OJO: No soy un experto en Datomic. En realidad, no le he dedicado más que unas horas para jugar con ella, por lo que es posible probable que parte de lo que diga no sea completamente cierto o, directamente, sea falso. Lo que pretendo con este post es poner en claro mi propias ideas y, si de paso, te sirve para aprender algo nuevo o despertar tu curiosidad, estupendo.

¿Qué es Datomic?

Datomic es una base de datos NoSQL con un clara inspiración en la programación funcional y las estructuras de datos persistentes (inmutables). Está diseñada por Rich Hickey, el creador de clojure, y eso se nota bastante. Aunque el tutorial oficial esté escrito en Java, el uso que hace Datomic del formato EDN para representar estructuras de datos deja claro el origen clojuriano de la base de datos.

Cumple con las propiedades ACID (igual que, por ejemplo, SQL Server) y tiene una arquitectura bastante curiosa basada en peers y transactors para poder separar lecturas de escrituras, tratando así de favorecer la escalabilidad y todas estas cosas que están tan de moda ahora que todos desarrollamos aplicaciones para cientos de millones de usuarios (ejem).

Cuenta con varios motores de almacenamiento, incluyendo un almacenamiento en memoria ideal para pruebas rápidas y desarrollo, y sistemas persistentes como Riak, DynamoDB, CouchDB o SQL.

Tiene varios modos de licenciamiento, algunos de ellos gratuitos (también en aplicaciones comerciales) y otros de pago que incluyen soporte y características avanzadas.

Representación de la información

Datomic es una base de datos con esquema, pero la forma en que se define un esquema en Datomic es completamente distinta de una base de datos relacional típica. En Datomic se definen atributos y, usando esos atributos, podemos almacenar la información de las entidades con las que queremos trabajar.

Cada atributo tiene, entre otras cosas, un nombre, un tipo y una cardinalidad (es decir, si puede tomar sólo un valor o admite varios valores).

Por ejemplo, podríamos definir los siguientes atributos para representar una entidad persona:

Nombre Tipo Cardinalidad
:person/name string 1
:person/age integer 1
:person/friends reference varios

Por convención, todos los atributos que van ligados a una misma entidad se marcan con el nombre de la entidad como prefijo (person/ en este caso), pero en realidad no es necesario.

Cada entidad de la base de datos tiene un id único y para representar la información que forma parte de una entidad, se establecen relaciones entre ese id y los valores de sus atributos.

Por ejemplo, si tuviésemos una persona con estos valores (representados en pseudo-json):

{
  "id": 900,
  "name": "Manolo",
  "age": 29,
  "friends": [101, 102, 103] /* ids de sus amigos */
}

En la Datomic estaría representada por algo parecido a esto:

; id   atributo         valor
[[900  :person/name     "Manolo"]
 [900  :person/age      29]
 [900  :person/friends  [101 102 103]]]

Representar la información de esta forma resulta un poco chocante al principio. En una base de datos relacional (SQL Server), la información de una persona estaría almacenada en al fila de una (o varias) tablas. O en una base de datos documental (MongoDB, RavenDB), tendríamos un documento dentro de una colección para representar a la persona.

Sin embargo, en Datamic lo que tenemos son asociaciones sueltas entre el id de la persona y sus atributos, y para conocer toda la información relacionada con una persona deberemos buscar todas los atributos asociados al id de la persona y ver qué valores toman. En cierto modo, podríamos verlo como una colección de hechos (facts) como los usados en programación lógica.

Como dije antes, no hay nada que haga que obligue a que todas las personas tengan los mismos atributos, y los atributos ni siquiera están ligados a la entidad persona. De hecho, puede haber casos en los que interese definir atributos «genéricos» que podemos utilizar en varias entidades (por ejemplo el nombre) y podríamos encontrar tanto personas como empresas con un atributo :common/name.

Esto es importante porque supone una gran diferencia a la hora de modelar los datos. Mientras que en SQL o MongoDB se modela la entidad como un todo, en Datomic se modelan atributos que asignamos a entidades, y esa asociación entre atributos y entidades es completamente implícita. En lugar de pensar en la entidad como tal, pensamos en los atributos que la definen.

Inmutabilidad

Datomic es una base de inmutable. Eso puede sonar raro (¿qué sentido tiene una base de datos que no puede cambiar?) pero en realidad la idea es sencilla: en Datomic nunca se modifica nada que ya esté en la base de datos, aunque podemos añadir cosas nuevas.

Para conseguir esto, cada vez que asociamos un atributo a una entidad, internamente se registra el instante en que tuvo lugar esa asignación, y en caso de que se actualice el atributo, se añade una nueva relación.

Por ejemplo, si a la persona que definíamos antes le cambiásemos el nombre, en la base de datos acabaríamos con dos registros asociando id a :person/name, cada uno de ellos en un instante diferente:

[[900 :person/name "Manolo" :date '2014-03-15T10:15:10.121']
 [900 :person/name "Manuel" :date '2014-03-15T10:17:45.874']]

Esto nos permite mantener un histórico del estado de la base de datos y poder consultar siempre cómo se encontraba la información en un momento determinado. Al almacenar la información como tuplas asociando ids con atributos, es una operación relativamente barata en términos de almacenamiento, ya que cuando modificamos un atributo de una entidad no hace falta copiar todos los demás atributos, sino sólo insertar el nuevo (podríamos asimilarlo a lo que hace un sistema de control de versiones como git, que almacena sólo los deltas entre revisiones en lugar de almacenar el fichero entero cada vez).

Además de la ventaja (obvia) de no perder nunca información de lo que ha ido pasando con nuestra información, esta manera de trabajar permite ver la base de datos como un valor. Es decir, podemos obtener una referencia a una base de datos en un momento determinado (generalmente el instante actual) y tratarla como un valor que nunca se modificará, por lo que nos ahorraremos problemas derivados de la concurrencia tan típicos en otras bases de datos y que acaban obligando a introducir bloqueos a nivel de tablas o niveles de aislamiento en transacciones muy restrictivos que limitan la concurrencia. Sería similar a ejecutar todas las transacciones en SQL Server con el nivel de aislamiento Snapshot, pero sin la penalización en rendimiento que ello conlleva.

Resumen

Datomic es una base de datos con un enfoque bastante alejado no sólo de las bases de datos relaciones, sino también de las (cada vez más) típicas bases de datos documentales estilo MongoDB, CouchDB, RavenDB y demás amigos.

Este post sólo ha sido una introducción muy superficial a lo que es Datomic, pero al menos debería servir para hacernos una idea de cuál es su filosofía. En próximos posts veremos como realizar operaciones básicas con Datomic, como definir un esquema, realizar transacciones o lanzar consultas.

8 comentarios en “Datomic, una base de datos diferente

  1. Hola Juanma

    Interesante esta base de datos, no la conozco, Neo4j si que la conozco y la potencia para ciertas funcionalidades de estas bases de datos es muy grande.

    ¿Cómo sería la comunicación desde código con esta base de datos? ¿Hay alguna librería para c#? o ¿tiene API Rest como neo4j?

  2. Hola Jorge,

    Datomic tiene un API Rest (http://docs.datomic.com/rest.html), pero está en Alpha y, además, no creo que sea la forma más cómoda de usarla.

    Yo te recomiendo que, si quieres jugar con ella, uses algún lenguaje sobre la JVM. Para mi el que tiene el API más lograda es clojure, pero desde scala, groovy o incluso java la puedes usar sin problemas.

    Un saludo,

    Juanma.

  3. Hola soy nuevo en el tema de los test de integración y ahora mismo tengo un problema y es que mis test acceden directamente a base datos(SQL Server) lo cual provoca que cuando no tengo conexión mis test fallan. No estoy usando ahora mismo ningún ORM, que me recomendarias montar mis test contra una BD en memoria? cual? o cual sería la mejor forma de hacerlo?
    Saludos y gracias por el post.

  4. Hola, recién conozco sobre datomic y me gustaría saber donde sacar la información documentada de datomic, gracias.

  5. Gracias Juana, me ha servido mucho la documentación, pero tengo algunas dificultades para instalar el datomic, he seguido todos los pasos que está en la documentación, sabes de algún tutorial de instalación ¿?

Comentarios cerrados.