featured image

Si te encuentras en la necesidad de conectar tu proyecto de Erlang/OTP con Mysql y tienes dudas de cual es el mejor driver para utilizarlo te comentamos algunas de las especificaciones, ventajas y desventajas de cada uno de los controladores que se han desarrollado y que se encuentran disponibles en Internet.

EMySQL

Emysql un desarrollo creado por EonBlast Corporation que dice ser el mejor driver para Erlang que existe, cuenta con ciertas deficiencias técnicas comentadas en la documentación del proyecto.

  • Sin un protocolo claro en la separación del pool de conexión
  • Sin un protocolo claro en la separación de sockets
  • Un complicado manejo del pool de conexiones, implementación propia
  • Utiliza protocolo de texto en muchos lugares donde debería ser un protocolo binario
  • La API debería ser mejor

Aun así comentan que sea probablemente el mejor controlador de MySQL en Erlang y que es considerado el mas estable utilizarlo en producción.

Este controlador de MySQL esta basado en erlang-mysql-driver y es un fork del proyecto original emysql.

Aunque recomiendan en el mismo README algunas alternativas dependiendo de las diferentes necesidades que tengas para tu aplicación:

  • Si es por estabilidad y alto rendimiento Emysql es la mejor opción
  • Si necesitas funciones básicas te recomiendan utilizar el controlador de ejabberd, simple, testeado a fondo, estable y con documentación dentro del código fuente.

Características

  • Emysql actualmente no soporta transacciones
  • Esta basado en Erlang/OTP
  • Contiene su propio pool de conexiones
  • Documentación detallada de utilización y con ejemplos claros
  • Tiene posibilidad de introducir comandos al momento de iniciar el proceso de conexión
  • Puede convertir los datos resultantes a records
  • Es capas de realizar búsquedas por LIKE
  • Soporta procedimientos almacenados
  • Permite definir declaraciones preparadas
  • Puede leer las sentencias de sql a través de un fichero de texto
  • Conversión de los resultados a JSON
  • Tiene un buen soporte para los tipos de datos
  • Tiene tests unitarios
  • Las sentencias de SQL se escriben en binario

Soporte de Tipos de datos

Realiza un buen manejo de retorno de los tipos de datos de MYSQL y añade información sobre el campo de la tabla que se esta utilizando.

Datos numéricos

El tipo de dato bit no está soportado y todos los datos de tipo numéricos son retornados en el mismo formato

Datos de fechas

Para el manejo de fechas se utilizan tuplas y se acompaña de un breve descripción del tipo de dato con excepciones, por ejemplo:

Si el tipo es Timestamp se mostrará de la siguiente manera:

[[{datetime,{{2012,12,31},{23,59,59}}}]]

Si es de tipo Time:

[{time,{13,59,59}}]]

La excepción aparece con el año retornando únicamente el número:

[[2015]]
Datos de tipo String

Todos los datos de tipo string son retornados en binarios.

Instalación, configuración e implementación

El proyecto esta en GitHub, su instalación es muy sencilla ya que utiliza rebar para compilarlo y no requiere de ninguna dependencia. La configuración es muy sencilla, se crea junto con el nombre del pool y la información para conectarse a la BBDD.

Para realizar las consultas únicamente se ejecuta la función emysql:execute/2 con el nombre del pool ya creado y la sentencia de SQL en binary.

Aquí un ejemplo:

-module(a_hello).
-export([run/0]).

run() ->
    crypto:start(),
    application:start(emysql),

    emysql:add_pool(hello_pool, [{size,1},
                                 {user,"hello_username"},
                                 {password,"hello_password"},
                                 {database,"hello_database"},
                                 {encoding,utf8}]),
    emysql:execute(hello_pool,
        <<"INSERT INTO hello_table SET hello_text = 'Hello World!'">>),

    Result = emysql:execute(hello_pool,
        <<"select hello_text from hello_table">>),

    io:format("~n~p~n", [Result]).

En la documentación se tiene varios ejemplos de todas las diferentes formas de utilizarlo como el cargar las sentencias de un fichero de texto o la conversión de los resultados a JSON.

Forks

En los distintos Forks que existen de este proyecto en Altenwald, Emysql se han añadido algunas mejoras significativas:

  • Manejo de transacciones
  • Estadísticas a través de folsom

Erlang-mysql-driver

Erlang-mysql-driver es un proyecto que parece ser esta abandonado por sus desarrolladores, en su página solo se especifica que está basado en Yxa driver desarrollado por Process One. Y tiene las siguientes nuevas características:

  • Soporte para transacciones
  • Declaraciones preparadas
  • Las sentencias de SQL se escriben en binario
  • Tipo de conversor para resultados
  • Logs mas eficientes
  • Tiene un nuevo mecanismo de pooling

Desventajas

  • No es compatible con rebar
  • No contiene test unitarios
  • No esta basado en Erlang/OTP no existen supervisores o gen_servers en el proyecto.
  • No hay continuidad en el proyecto.

Parece ser que fue un intento de mejorar, pero se quedo solo en el intento.

ErlMysql

Erlmysql es un proyecto desarrollado por Alexei Krasnopolski en su versión 1.2.4 y parece ser una buena alternativa a Emysql.

El proyecto tiene una excelente documentación y esta muy bien organizado, en su página comentan que podría compararse con el conector escrito en C (Connector/C) aunque con algunas restricciones.

Características

  • Actualmente no tiene soporte de SSL
  • Esta basado en Erlang/OTP en su arquitectura.
  • Utiliza erlpool para las conexiones y para la concurrencia
  • Utiliza supervisores para cada uno de los hijos creados por el pool
  • Documentación detallada de utilización y con ejemplos claros
  • Soporta transacciones
  • Tiene pruebas unitarias
  • Utiliza rebar para su compilación
  • Las sentencias de SQL son de tipo lista
  • Los resultados incluyen metadata de los campos seleccionados
  • Pueden crearse cursores para navegar con los resultados obtenidos
  • Permite definir declaraciones preparadas
  • Tiene buen soporte para los tipos de datos
  • Tienen un manejo de errores y excepciones
  • Tiene soporte para el protocolo de compresión
  • Permite enviar longdata

Soporte de tipos de datos

Erlmysql tiene capacidad de manejar todos los tipos de datos, además incluye información detallada metadata sobre los campos que se están consultando.

Tipo de datos numéricos

A diferencia de Emysql, Erlmysql es capaz de soportar el tipo de dato Bit.

Tipo de datos de fechas

Las fechas se presentan con un único formato. Algunos ejemplos:

Timestamp

[[{mysql_time,false,2012,12,31,23,59,59,0}]]

Date

[[{mysql_time,false,2015,12,31,0,0,0,0}]]

Time

[[{mysql_time,false,0,0,0,1,59,59,0}]]

Al igual que Emysql para seleccionar el tipo de año se presenta como numérico.

[[2015]]
Datos de tipo String

A diferencia de Emysql que entrega todos los resultados en binary, Erlmysql hace diferencia de los tipo de datos de texto retornándolos en listas y los de tipo varchar o blob los retorna en binary.

Cursores

Ermysql cuenta con un sistema de cursor para navegar por los datos entregados de MySQL, cada proceso crea su propio cursor así solo puede acceder al que lo ha creado y no a los demás procesos por lo que no puede ser concurrente.

Las operaciones permitidas son:

  • reset: inicializa el puntero del cursor al inicio
  • next: mueve el puntero a la siguiente posición
  • set: mueve el puntero una posición especifica
  • skip: omite algunas posiciones de la cabecera
  • back: mueve el puntero a una posición anterior
  • foreach: retorna la lista de valores dados por un campo en todas las tuplas

Declaraciones preparadas

Erlmysql permite definir declaraciones preparadas (prepared statements), es una sentencia de SQL con el parámetro (?) y utilizado para realizar una consulta mas específicas utilizando los tipos de datos

Manejo de errores y excepciones

ErlMysql es capaz de detectar algunos de los errores y excepciones utilizando el record #mysql_error.

Algunos de los errores son:

  • tcp: si existe algún error de socket creado para la conexión de red.
  • connection: errores de conexión a la BBDD
  • sqlquery: errores durante la consulta de SQL
  • statements: prevé la ejecución de la consulta al no utilizar los parámetros correctamente
  • transaction: errores durante la transacción

Transacciones

Erlmysql dispone de un soporte sencillo transacciones para realizar operaciones de persistencia y/o consultas, el sistema puede devolver un registro de error o cualquier otro tipo de dato si la transacción ha tenido éxito.

p1_mysql

p1_mysql Proyecto realizado por processone y utilizado por ejabberd.

El proyecto cuanto con la mínima documentación descrita en los comentarios del código.

Características

  • Esta basado en Erlang/OTP en su arquitectura.
  • Utiliza su propio pool para las conexiones
  • Documentación mínima descrita en el mismo código
  • No Soporta transacciones
  • No contiene pruebas unitarias
  • Utiliza rebar para su compilación
  • No hay un buen soporte para el tipo de datos
  • Las sentencias de SQL son de tipo lista
  • Los resultados incluyen el tipo de dato que se esta consultando

Soporte de tipos de datos

p1_mysql no tiene un buen soporte para los tipos de datos de Mysql como los controladores antes mencionados, es muy básico y habrá que realizar una conversión después de que sean entregados los resultados.

Tipo de datos numéricos

Todos los datos numéricos son tratados como listas e incluyen el tipo de dato que se esta entregando:

{data,{p1_mysql_result,[
    {"numeric_table","data_smallint",6,'SHORT'}
],[["32767"],["-32767"]]
Tipo de datos de fechas

Las fechas son entregadas en lista con formato muy parecido a como lo maneja MySQL por ejemplo:

Timestamp

[["2012-12-31 23:59:59"]]

Date

[["2015-12-31"]]

Time

[["01:59:59"]]

El tipo año también es entregado en lista:

[["2015"]]
Datos de tipo String

Todos los datos de tipo string y char son entregados en listas.

Conclusiones

Después de revisar todas las características de cada uno de los controladores aquí especificados creo que el mejor es el driver de Emysql, ya que es el que tiene mejor soporte de datos, es rápido y el que tiene mas características para manejar MySQL junto con una buena documentación.

Características Emysql Erlmysql p1_mysql erlang-mysql-driver
Basado en OTP No
Utiliza rebar No
Pool de conexiones Propio erlpool Propio Propio
Soporte de datos No No
Soporte de transacciones No No
Pruebas unitarias No No
Documentación No No
Manejo de errores y excepciones No No No
Soporte procedimientos almacenados No No
Conversor de resultados a JSON No No No
Leer las sentencias a través de un fichero de texto No No No
Soporte del compresión No No No
Soporte de prepared statement No No
Sistema de cursores para manejar los datos No No No
Manejo de Blob transfer No No No

Pruebas de velocidad

Hemos realizado algunas pruebas de velocidad utilizando eprof en cada uno de los controladores, para medir el tiempo que tardaban en realizar consultas simples de todos los diferentes tipos de datos que maneja MySQL.

Se han creando 3 tablas con los diferentes tipos de datos:

Tabla de fechas:

CREATE TABLE date_table (
    data_date date,
    date_datetime datetime,
    data_timestamp timestamp,
    data_time time,
    data_year year);

Tabla numérica:

CREATE TABLE numeric_table (
    data_bit BIT(8), 
    data_tinyint tinyint,
    data_bool bool,
    data_smallint smallint,
    data_mediumin mediumint,
    data_integer integer,
    data_bigint bigint,
    data_decimal decimal(4,2),
    data_float float,
    data_double double(9,8));

Tabla string y chars:

CREATE TABLE string_table (
    data_varchar varchar (20),
    data_text text (255),
    data_binary binary (8),
    data_varbinary varbinary (8),
    data_tinyblob tinyblob,
    data_blob blob (100),
    data_mediumblob mediumblob,
    data_longblob longblob,
    data_longtext longtext);

Nuestro objetivo es saber cuanto tarda cada uno en realizar una consulta sencilla, por lo que hemos agregado un solo registro en las tablas. Se han ejecutado 1000 veces cada una de ellas y los resultados son los siguientes:

MySQL Driver Tiempo (segundos)
Emysql 21,931883
Erlmysql 8,560329
p1_mysql 7,171054
erlang-mysql-driver N/A

Como podemos ver, el más rápido en realizar las consultas fue p1_mysql la razón es por que hace ninguna conversión de los tipos de datos, todos los entrega en listas.

El segundo con un mejor tiempo fue Erlmysql con 8,56 segundos, casi un segundo mas que p1_mysql incluyendo la conversión de los tipos de datos mas la información adicional o metadata.

Por último con 22,51 segundos tenemos a Emysql que ha sido el que mas ha tardado con diferencia.