Modelos experimentales de persistencia para aplicaciones web (II): Object Freezer-Relational

En el anterior post vimos un invento de Sebastian Bergmann llamado Object Freezer, que consiste en almacenar objetos PHP en CouchDB de forma automática. Es un buen método para no tener que definir esquemas de bases de datos, escribir sentencias SQL, hacer mapeo objeto-relacional… en definitiva, es una solución que nos puede ahorrar un montón de trabajo.

Pero, una vez aceptadas las ventajas de la congelación, quizá sea necesario guardar esos objetos en una base de datos diferente a CouchDB. Por ejemplo, en MySQL. Y de esto trata el presente artículo: de congelar objetos y guardarlos en MySQL.

Un brevísimo repaso a la congelación

Congelar un objeto (“freeze”) es convertirlo en un array manteniendo los objetos hijos y evitando duplicidad de los mismos. La operación inversa, la descongelación (“thaw”), sería recoger ese array y convertirlo de nuevo en el objeto original.

¿Por qué MySQL, si con NoSQL nos ahorramos todo el trabajo?

  1. A veces no es viable o rentable cambiar de servidor de bases de datos, por la inversión económica y de formación que requieren los sistemas tradicionales.
  2. Interoperabilidad: si en el futuro queremos migrar la aplicación, quizá poder manipular la información con SQL facilite la tarea.
  3. Rendimiento: las bases de datos relacionales se basan en algoritmos muy evolucionados y rápidos, y sistemas como MySQL-MyISAM han demostrado un rendimiento muy alto.

Entonces… ¿Se trata de guardar arrays en MySQL?

Exacto. Eso es lo que hace Object Freezer-Relational, una extensión de Object Freezer escrita por un servidor :-)

Lo primero que debemos pensar a la hora de guardar objetos en MySQL es: ¿cuál es el esquema de tablas? Porque si con CouchDB éramos NoSQL y guardábamos la información en arrays JSON, ahora tenemos que ceñirnos al álgebra relacional, las tablas, los índices y las claves primarias.

Así que este es el esquema que podemos usar:

  • Tabla objects
    • id: el ID único del objeto.
    • className: indica la clase de la cual es instancia el objeto almacenado.
    • isDirty y isRoot: dos atributos que utiliza Object Freezer internamente.
  • Tabla properties
    • name: nombre del atributo.
    • value: contiene el valor del atributo o bien un ID si el atributo hace referencia a otro objeto.
    • type: tipo de dato (int, float, string, boolean, array, objeto…).
    • object_id: ID del objeto al que pertenece el atributo. Hace referencia a objects.id.

Llegados a este punto uno podría pensar: “hey, te estás cargando el modelo relacional”. Efectivamente. Si queremos guardar objetos sin definir su esquema de BD, no nos queda más remedio que soluciones experimentales como la que te presento hoy. Sí, es una “des-normalización”, pero gracias a ella te ahorras escribir SQL.

Object Freezer-Relational se encarga de gestionar este esquema. De hecho, no es siquiera necesario crearlo, ya que lo hace automáticamente.

Vale, ya veo que mola. ¿cómo se usa?

Usar Object Freezer-Relational es tan sencillo como usar Object Freezer indicando los datos de acceso a MySQL:

$storage = new Object_Freezer_RelationalStorage(
    new Object_Freezer,
    NULL,
    FALSE,
    new MysqlStorage(
        "localhost",                    //Servidor MySQL
        "freezer",                      //Usuario
        "passw0rd",                     //Contraseña
        "freezer",                      //Base de datos
        3306,                           //Puerto
        MysqlStorage::ENGINE_INNODB));  //Motor MySQL

A partir de ahí, podemos usar el objeto $storage de la misma forma que el Object Freezer original, con CouchDB, ya que es la misma API.

Object Freezer-Relational está disponible en SourceForge. Puedes descargarlo y probarlo, echar un vistazo al código o leer la documentación si te interesa. Y por supuesto, comentar qué te parece la idea de guardar objetos en una base de datos MySQL :-)

Ajustando la cache de consultas de MySQL para un mejor rendimiento de Drupal

¡Hola de nuevo! Después de un tiempo de inactividad voy a retomar el blog, aunque no prometo publicar muy asiduamente :-P

Continuando el hilo post anterior (mayo de 2010, ¡la de cosas que han pasado desde entonces!), vamos a ver cómo aumentar el rendimiento de un sitio Drupal, en este caso a través de la cache de consultas de MySQL.

En /admin/reports/status/sql, Drupal muestra algunas estadísticas interesantes del servidor MySQL, que nos dan pistas sobre lo bien o mal optimizado que tenemos el sistema: número de consultas cacheadas, ordenaciones sin índices, etc.

En la explicación de alguno de los indicadores se indica “debe ser cero”. Estos indicadores son Select_full_join, Select_range_check y Sort_scan. En términos generales, si estos valores son altos se debería modificar el esquema de la BD añadiendo índices, aunque si estamos hablando de Drupal esta situación no debería darse, ya que el esquema tiene índices correctamente establecidos.

Otro indicador interesante es Qcache_lowmem_prunes. Indica “el número de veces que MySQL tuvo que retirar consultas del caché porque se quedó sin memoria”. En mi caso, este indicador mostraba el alarmante valor de 349102 (¡desde que se arrancó el servidor!).

Para arreglar esta situación vamos a aumentar el tamaño asignado a la caché de consultas. Lo haremos desde el fichero de configuración de MySQL (my.cnf):

query_cache_limit = 1M
query_cache_size = 32M

El primer parámetro es el tamaño máximo de las consultas “cacheables”. Lo usaremos para evitar cachear consultas lentas o muy grandes, que suelen ser infrecuentes (y por tanto no tiene mucho sentido cachearlas).

El segundo parámetro es la cantidad de memoria que queremos asignar a la caché. Cuanta más memoria RAM tenga nuestro servidor, mayor valor podremos darle. En mi caso el servidor tiene 512MB, de los cuales alrededor de 200 están ocupados por el sistema y los servicios (Apache, el propio MySQL, memcache y los servicios de correo). Así que puedo aumentar el tamaño del cache hasta 50MB.

Después de reiniciar el servidor, lleva 95 días funcionando y arroja un valor de 3451 purgas. Muchas menos que con la anterior configuración.

Esta es una medida sencilla que ayuda a optimizar la cache de consultas de MySQL, un sistema que impacta en el rendimiento global del sistema, sobre todo si no tienes un sistema de caché fuera de MySQL.

¿Qué hay detrás de Amazon SimpleDB?

Estos días he estado informándome sobre los Amazon Web Services, más concretamente el relativamente reciente SimpleDB, un poco por escepticismo hacia la moda del Cloud Computing, o mejor dicho, a la moda de hablar sobre el Cloud Computing (qué queréis que os diga, tampoco me parece tan novedoso el invento). El servicio es un gestor de BBDD no relacional y no orientado a objetos, situado en nosedonde, gestionado de nosequé manera (cloud computing, vamos). Este gestor de BBDD es tan sencillo de entender como que tenemos dominios y, dentro de los dominios, registros con pares propiedad-valor. Estos pares no están definidos, por lo que podemos decir que es una base de datos sin esquema, sin estructura previamente definida. Genial, parece útil para ciertos programas.

El caso es que desde hace algún tiempo estoy recopilando información sobre Oracle BerkeleyDB (Oracle compró SleepyCat, desarrolladora original), un gestor de bases de datos embebido, no relacional, no orientado a objetos, y encima Open Source. Genial, parece útil para ciertos programas. Coño, dejá vu. Y encima voy a la web de BerkeleyDB y me encuentro este case study de Julio de 2008 en el que Tim Kohn, jefe de servicios explica que BerkeleyDB es usado como caché para la gran base de datos de Amazon (como tienda, no como proveedor de servicios web), delante de un Oracle DB normal (el artículo indica el talento que tienen en Amazon).

Interesante. Buscando un poco más me encuentro con que el desarrollo de Amazon para integrar BerkeleyDB, Oracle y los demás sistemas ha evolucionado y le han llamado Dynamo. Aunque su autor empieza diciendo que:

Dynamo is not directly exposed externally as a web service; however, Dynamo and similar Amazon technologies are used to power parts of our Amazon Web Services, such as S3.

…aunque teniendo en cuenta que fue publicado hace un año, la verdad es que es bastante probable que SimpleDB sea una interfaz, o directamente instancias, de Dynamo, esa combinación de BerkeleyDB y MySQL:

[...] BDB can handle objects typically in the order of tens of kilobytes whereas MySQL can handle objects of larger sizes. Applications choose Dynamo’s local persistence engine based on their object size distribution. The majority of Dynamo’s production instances use BDB Transactional Data Store.

Conclusiones:

  • Leyendo ambos artículos uno se da cuenta de lo buenos que son los informáticos de Amazon. Normal, dado que son una de las empresas más potentes de Internet y manejan una de las Base de Datos comerciales más grandes del mundo.
  • Open Source matters, como dicen los de Joomla. Y las empresas lo saben, cada vez mejor. Y sobre todo por las malas lenguas que desprecian a MySQL como RDBMS incompleto en comparación con PostgreSQL. Soy fanático de MySQL y es cierto que es un DBMS muy sencillo, está algo verde y en algunas cosas resulta “de juguete” (sobre todo en comparación con el gigante Oracle), pero la escalabilidad y rendimiento que ofrecen lo hacen líder para Internet y entornos como los de AmazonWS.
  • En el caso de BerkeleyDB ha habido una apuesta fuerte por parte de Oracle, aunque Amazon ya la usaba antes de ser adquirida por el grande de Redwood City. Un DBMS original, sencillo, que desafía a los tradicionales RDBMS que nos enseñan en la universidad como la única solución posible. Además, existe BerkeleyDB XML, una interesante Base de Datos estructurada que emplea XQuery. Puede dar mucho que hablar en el futuro, sobre todo de cara a las BBDD semánticas.
  • El cloud computing en BBDD, como las demás tendencias 2.0 (odio esa etiqueta, la odio, la odio!!) no aporta ninguna innovación tecnológica (en este caso Dynamo ha sido un implementación para hacer posible una aplicación, pero BDB y MySQL ya existían), pero es una gran oportunidad para ahorrar costes en mantenimiento y tiempo en desarrollo.

¿Qué opinión os merece SimpleDB? ¿Y los servicios de cloud computing en general? ¿Os gustan, no os gustan, ponen en peligro vuestros empleos…?