8 lecciones aprendidas optimizando MySQL

Hace unas semanas estuve bastante entretenido optimizando una base de datos MySQL razonablemente grande, unos 18 millones de filas ocupando más de 10Gb de datos usada por un sitio web con un tráfico de más de 11 millones de visitas mensuales. No optimizar el rendimiento en este caso sería un grave error así que he aprendido y disfrutado mucho durante estos días.

Lo primero que aprendí es que los servidores de base de datos con bestias complejas –no las subestimes– y cada una de ellas tiene sus fortalezas pero tambien sus propios problemas.

Más tarde o más temprano deberás enfrentarte a comportamientos que parecen completamente contraintuitivos y toca leer mucha documentación para comprender estas cosas. En este caso, MySQL Performance Blog y la documentación de MySQL han sido de gran ayuda pero también Hack MySQL que, aunque ya no se actualiza ofrece muy buenos consejos bien explicados.

Como siemre, hacer el 80% de la optimización consume el 20% del tiempo porque suele ser relativamente sencilla. Hacer un EXPLAIN, ver los resultados, crear el índice adecuado y comprobar con EXPLAIN que funciona como debe. Con este esquema básico se puede hacer un buen trabajo simplemente sabiendo lo básico de indexación. Puede que no sean los índices más óptimos pero harán su trabajo.

Después tienes que ser paciente, crear índices no siempre es rápido. De hecho, el número, el tamaño y la heterogeneidad de las columnas afectadas aumentan el tiempo que se tarda en crear el índice. Mientras esperas lo mejor es leer buenos libros sobre MySQL o bases de datos relacionales como: Relational Database Index Design and the Optimizers.

Tienes que ser organizado. Crear índices aleatoriamente simplemente mirando un par de SELECTs lentos es algo, pero tienes que mirar con perspectiva: haz un inventario de todas las consultas de la aplicación, no importa lo poco importantes que parezcan porque si atacan a una tabla grande con un WHERE o un ORDER BY tendrán un rendimiento muy pobre. Esta lista te ayudará a organizar los índices y ver cuáles son usados y cuáles no y dónde.

Aprende bien qué significan los parámetros de configuración. MySQL tiene un montón. Simplemente aumentando los valores no desatascarás tus cuellos de botella. Si ves algo raro es posible que algún parámetro esté mal configurado y causando problemas. Hay un script PERL llamado MySQL Tuner que nos puede dar buenas pistas.

A veces te sentirás frustrado por algo que no comprendes. Si algo he descubierto es que casi todo en este campo tiene una explicación –incluso una razonable y lógica–.

Finalmente no descuides el resto de cosas. El rendimiento de la base de datos es importante pero puede que haya mucho por mejorar en tu código, ¡no eches siempre la culpa a la base de datos de todos los problemas!

Posted in Programación | Leave a comment

Reflexiones tras #VLCTESTING

Hace unos días tuve la suerte de asistir a la primera edición de las jornadas VLCTESTING organizadas por el Instituto Tecnológico de Informática de la UPV, que toman el testigo que las JTS dejaron en 2008. Y creo que, pese a ser un evento modesto, han cumplido las expectativas y hubo más de 100 asistentes que seguro volverán en próximas ediciones.

Como siempre en este tipo de actos, hay de todo un poco y a cada uno le gustarán más unas ponencias que otras. Yo personalmente, dado que me dedico al desarrollo de software en una pequeña empresa, las que tratan de los procesos de calidad en grandes corporaciones me quedan un poco grandes y me resulta complicado sacar provecho de ellas.

Empezaron las jornadas con la presentación de Maxi Mannise, director del Área de Calidad del Software del ITI: “Probado ¿Reprobado? … ¡Re-Probado!” – Un juego de palabras –, que sirvió como entrante de las jornadas dando un repaso general al testeo y los procesos de calidad.

Después vino la presentación de AtoS, con una interesante segunda parte sobre cómo se preparan los sistemas informáticos de los JJOO, recordándonos la importancia de que todo esté bien probado dado que no se pueden permitir ningún fallo – incluso hay un equipo dedicado a “romper” los sistemas y ver cuánto tardan en arreglarlos –.

La siguiente vino a cargo de Antonio Robres sobre las cualidades de un buen tester. Una presentación sencilla que hacía mucho hincapié en las soft skills del perfil, aunque considero que dichas habilidades no solamente son buenas en un tester sino en cualquier persona que ha de trabajar en grupo.

Después vino una presentación de Javier Pello sobre Quality Assurance que me quedó un poco lejana – tanto deliverable arriba y abajo me marea – y tras la pausa otra de Bull alrededor del outsourcing de proceso de calidad del software (QaaS), un poco de propaganda, pero para algo patrocinan.

Me gustó mucho la presentación de QAlitaX, tanto por el ponente, Antonio Calero, como por el contenido, versado en las métricas de calidad del software y los resultados obtenidos – no demasiado buenos, todo sea dicho – después de analizar unos 50 proyectos de software de todos los tamaños. Me dio muchas ideas de qué y cómo medir, que seguro aplicaré en el día a día. Introdujo además el concepto de deuda técnica, que es la medida en € de lo que costaría conducir el proyecto a unos estándares adecuados de calidad. Y los números asustan.

La siguiente presentación trataba el mismo tema pero de una forma un tanto más densa. En resumen: medir para saber dónde actuar.

Y antes del café, Maite Tamayo nos desveló lo que era un sistema metrológico – a mí me tenía intrigado – y cómo tuvieron que meterse en la cabeza de los metrólogos y lidiar con sus máquinas para poder testear en condiciones un sistema bastante complejo. Fue bastante específica pero me hizo gracia ver cómo las cosas se iban complicando por momentos.

La última parte pretendía ser más práctica y lo consiguió a medias. Empezó bien con la usabilidad de la mano de Jordi Sánchez y el botón de los $300M. Uno de los grandes olvidados en el diseño de UI es la usabilidad y la presentación mostró cómo puede ser la diferencia entre el éxito y el fracaso, cómo un simple botón puede llevarnos a la ruina por no tener en cuenta a los usuarios. Además curiosamente fue la única presentación que trató algo sobre los entornos web, que desde el punto de vista del testeo son muy interesantes.

El software crítico no tiene fallos ¿por qué? Pues nos los explicó Eduardo Lluna, también del ITI: cómo se desarrollan proyectos para este tipo de software que no puede tener errores. Básicamente se trata de hacer, revisar y verificar de forma minuciosa en cada una de las fases de desarrollo, que además son bastante estrictas.

Y para terminar una pequeña introducción al testing combinatorio y un algoritmo desarrollado por la ponente en su doctorado y su aplicación a un sistema financiero real de proceso de pagos con tarjeta. El testing combinatorio la verdad que puede tener sus usos, está bien tenerlo en el arsenal de técnicas.

Y hasta aquí llegó mi VLCTesting. Al final no fui al AutumnTest pero a ver si a la próxima me apunto a esas cervezas.

Nos vemos el año que viene.

Enlaces

Posted in Programación | Tagged , | 3 Comments

Hola de nuevo

Podría decir que este blog es nuevo pero en realidad dista bastante de serlo. Necesitaba un sitio donde poner entradas en español relacionadas con mi propia experiencia tecnológica apartadas de climens’ codelog, que quedará reservado a las entradas en inglés únicamente, pasando todas las que estaban en español en ese otro blog a este por arte de magia.

La magia viene servida por redirecciones 301 de mano de Quick Page/Post Redirect Plugin de modo que cualquier visitante que tenga guardada una URL antigua será redirigido a la nueva y no se perderá el posicionamiento en Google.

De hecho, uno de los motivos para separar los blogs en 2 es para poder medir mejor qué parte del tráfico es en inglés y qué parte en español y dar una mejor experiencia a los usuarios hispanohablantes y angloparlantes.

Un saludo, y bienvenidos de vuelta.

Posted in Sin categoría | Leave a comment

Cambio de hosting

Durante este fin de semana tengo previsto cambiar de hosting (de DreamhostSilicontower) y de versión de WordPress, así que es posible que ocurran cosas extrañas durante un par de días.

Que la fuerza me acompañe.

Posted in Programación | Leave a comment

NHibernate y localización

Edit: Cross-posted in NHForge: Localization techniques

Hace unos días estuve dándole vueltas en el grupo de NHUsers de nuevo al tema de la localización de propiedades usando NHibernate para ver si se me ocurría una forma más potente de hacerlas, dado que el mecanismo que usamos actualmente no permite usar ordenación a través de SQL, por lo que para ordenar los datos por la columna localizable, hay que procesar todas las entidades, lo que es un problema cuando hay muchas.

En resumen, hay 2 modos fundamentales y ampliamente documentados de hacer campos localizables con NHibernate.

Método 1: Serializando la propiedad a través de un IUserType

Esta aproximación es por ejemplo la que describe Fabio Maulo en su blog, usando LocalizablePropertyType del proyecto uNHaddins. Básicamente se trata de almacenar todas las cadenas de traducción en un solo campo y el IUserType se encarga de obtener un diccionario u otra estructura más compleja a partir del valor del campo y de almacenar esa misma estructura en forma de string.

En mi caso, no usé exactamente este tipo porque quería almacenar también un identificador de idioma por defecto y algunas cosas más, pero no es algo complicado de hacer.

Internamente normalmente almacenaremos algún tipo de diccionario con el idioma como clave y el valor la traducción pero es sencillo exponer la propiedad como un string haciendo que el get obtenga el valor correcto para el idioma actual (si es que esta funcionalidad no la implementamos en nuestro propio diccionario).

Ventajas:

  • Sencillo de realizar
  • No se necesitan tablas adicionales
  • Transparente

Inconvenientes:

  • Al ser un campo calculado, no permite usar ORDER BY
  • La propiedad no puede ser un string

Método 2: Almacenar la propiedad en otras tablas

Hay varios ejemplos de cómo realizar esto, básicamente se trata de mapear la propiedad a una estructura de tipo diccionario donde se almacenan las distintas traducciones del valor de la propiedad indexadas por código de la localización (bien en texto o usando el LCID). Esto se puede hacer más o menos complejo, pero fundamentalmente el principio es el mismo.

Todo esto se suele apoyar en una clase que se encarga de almacenar el diccionario de localizaciones y provee métodos para añadir, eliminar y obtener de forma sencilla dichas cadenas, haciendo uso del Thread.CurrentThread.CurrentCulture para obtener el idioma seleccionado actualmente.

Como no, Ayende ofrece una solución al problema basada en la simplicidad en Localizing NHibernate: Contextual Parameters, usando una fórmula en el mapping para obtener la propiedad Name de la entidad y un filtro en la sesión para que funcione la fórmula. Igual no soluciona los problemas en todos los escenarios, pero es una lectura interesante.

En esta otra propuesta de WebDevBros, Michal nos propone Create a multi languaged domain model with NHibernate and C#. Muy interesante. Por un lado, se crean dos tablas, una con los diferentes diccionarios que corresponderán a las distintas propiedades a localizar, y otra tabla con los valores de cada diccionario, que se mapea con un <map> de forma sencilla. También una clase que sirve para contener las traducciones y facilitar el acceso a las mismas.

En esta misma linea, Siim Viikman muestra en Mapping translations in NHibernate una aproximación muy similar a la anterior que conviene también leer porque aporta otra variante a la solución. Esta quizás no es tan cómoda de usar como la anterior pero puede tener sus ventajas.

En Localizable entities with Nhibernate (Part1, Part2 y Part3), Alkampfer propone una solución algo compleja, que se basa en un objeto que mantiene el idioma actual seleccionado durante el ciclo de vida de la aplicación y en una clase de apoyo que gestiona las traducciones. Es de lectura muy interesante aunque en mi opinión se puede hacer lo mismo evitando el objeto Registry que crea y usando Thread.CurrentThread.CurrentCulture.

Ventajas:

  • Uso de todas las posibilidades de la base de datos y SQL

Inconvenientes:

  • Mapeo más complejo (dificil en algunos casos o imposible usando Fluent NHibernate)
  • Más tablas, más datos

Conclusión

En resumen, las propiedades traducibles o localizables son un problema difícil de resolver que generan una capa de complejidad en el acceso a datos y en la gestión de dichas traducciones. Aun así me puedo aventurar a dar ciertos consejos

  • Antes de localizar una propiedad, pensar si realmente es necesario ¿realmente es necesario?
  • Si no vamos a necesitar ordenación u indexación por SQL, el método basado en IUserType es más que suficiente y ahorramos problemas. NOTA: Si se quiere indexación, siempre se puede usar Lucene.NET y NHibernate.Search con un Bridge personalizado que almacene todos los idiomas.
  • Si necesitamos ordenación, seguramente será solo en algunos campos concretos, así que podemos solamente usar el segundo método en los campos más críticos para simplificar nuestra vida.

En mi caso al final hemos optado por una solución mixta, usando el primer método en la mayoría de los casos y cuando se ha necesitado tener listados grandes ordenados por la propiedad localizable, hemos optado por una solución parecida a la de WebDevBros pero con una tabla por cada campo localizable porque no son muchos y el mapeo es más simple.

Posted in Programación | Tagged , , | Leave a comment

Lo mejor de 2009

Como cada año, este post hace un repaso de lo más leído de 2009. La verdad que ha sido un año de altibajos, con pocas entradas pero en mi opinión de mejor calidad y más específicos y útiles (para el que le sirvan) que los publicados anteriormente. Además he introducido algunos posts más en inglés con temas que creo que no estaban explicados en ningún sitio.

El más leido de 2009, NHibernate Burrow and NHibernate Search, explicando la integración de estas dos estupendas librerías. Burrow permite manejar sencillamente las sesiones de NHibernate en entornos web y Search permite integrar con Lucene. También escribí la versión en español del artículo.

Más de NHibernate: NHibernate Validator custom messages, o cómo conseguí personalizar los mensajes del validator mediante extensibilidad de un modo muy sencillo y potente. Supongo que con el tiempo Validator soportará esto nativamente.

Después otro más en inglés, ASP.NET MVC and ReturnUrl, quejándome de que muchos ejemplos de autenticación con MVC no respetan el parámetro ReturnUrl correctamente, lo que es un error a la hora de hacer un mecanismo útil de autenticación.

Y por último, los Principios básicos de OOP: SOLID que siempre deberíamos tener todos presentes a la hora de diseñar una aplicación y mantener la coherencia, la facilidad de uso y la mantenibilidad.

Y dado que este año no he escrito mucho, lo voy a dejar aquí. En 2010, más ASP.NET MVC, más NHibernate y más de todo.

¡Feliz 2010!

Posted in General | Tagged , | Leave a comment

Mis feeds sobre NHibernate y ASP.NET MVC

Hace tiempo que tengo un par de feeds en Google Reader que me gustaría compartir con todo el mundo que le puedan interesar.

El primero es sobre NHibernate y el segundo sobre ASP.NET MVC, dos temas que sigo de cerca porque los uso diariamente en mi trabajo, recogiendo noticias que van apareciendo en los blogs a los que estoy suscrito. Por supuesto hay muchas en inglés porque la mayoría de la información se publica en este idioma aunque intento poner cosas en español también:

Espero que resulten de utilidad.

Posted in Programación | Tagged , | Leave a comment

El principio KISS

Beauty in SimplicityEl nombre del principio es el acrónimo del inglés Keep It Simple, Stupid o Keep It Short and Simple. El sentido, se puede imaginar. Es en realidad la aplicación de lo que se conoce como La Navaja de Occam (Ockham’s Razor) aplicado a la informática. Todo se basa en una simple premisa: “dadas dos soluciones a un problema determinado, la más simple es probablemente la correcta”.

Aplicado al mundo del desarrollo de software, lo que se conoce como el principio KISS, implica resolver los problemas del modo más sencillo posible y posiblemente ésta sea la mejor solución.

Código
Desde el punto de vista del código tiene más implicaciones a parte de la simplicidad:

  • Un código más simple es más sencillo de mantener, lo que ahorrará tiempo en el futuro.
  • Además, será más sencillo de comprender por cualquier persona que entre en el equipo de desarrollo.
  • Cuesta menos de escribir
  • Menos lineas equivalen a menos bugs, lo que significa código de mayor calidad

Gestión de proyectos
Pero todo esto carece de sentido si desde no se tiene también en cuenta desde el nivel de gestión de los proyectos de software. Es estupendo pensar en miles de funcionalidades para un producto pero ¿qué sentido tienen? Primero habrá que hacer lo más simple para luego ir añadiendo más cosas a una base sencilla y comprensible.

Hay que construir software sobre una base sólida y unos requisitos simples y concretos. Esto permitirá desarrollar unas funcionalidades simples y robustas en menos tiempo y una vez el producto tiene cara y ojos, se pueden ver las carencias y se pueden encontrar nuevas posibilidades.

Pensar en cientos de funcionalidades, además tiene otras implicaciones menos obvias:

  • Tests de usuario menos frecuentes pero mucho más complejos y largos.
  • Bugs más difíciles de encontrar y de solucionar.
  • Time-To-Login (tiempo entre que se empieza el desarrollo hasta que se tiene una primera release) mucho más alto.

Muchas de las metodologías ágiles se basan en parte en este principio para desarrollar un software evolutivo en vez de crear gran cantidad de especificaciones y documentos que pueden tardar años en implementarse y meses en integrarse.

En resumen, antes de escribir un método, piensa si no lo estás complicando demasiado y antes de añadir un requisito a una release… piensa si realmente es necesaria en ese momento. Recuerda: KISS.

Posted in Programación | Tagged , | 4 Comments

Principios básicos de OOP: SOLID

Últimamente reviso mucho código, tanto mío como de otros y me doy cuenta de que muchas veces se pasan por alto los principios básicos del paradigma de orientación a objetos y en muchos casos porque la formación es deficiente o inexistente.
Así pues, uno de los acrónimos en el mundillo de la programación orientada a objetos (OOP) es SOLID, que sirve de regla mnemotécnica para recordar 5 principios básicos:

SRP: Single Responsibility Principle:
El principio de responsabilidad única nos dice que nunca debe haber más de un motivo para que una clase cambie, o lo que es lo mismo, que una clase solamente debe tener un propósito. Esto parece simple pero en realidad es uno de los principios más fáciles de violar y muchas veces no es fácil distinguir las responsabilidades.

OCP: Open-Closed Principle:
El principio abierto/cerrado implica que las clases de software deben estar abiertas para la extensión pero cerradas para la modificación. Este es el principio por el cual se hacen privadas las variables del miembro o que no se usan variables globales. El truco de este principio está en la abstracción. Las clases abstractas implementan un código inalterable desde fuera pero obligan a extender de ellas para usar este código a parte de que se promueve la reusabilidad.

LSP: Liskov Substitution Principle:
El principio de sustitución de Liskov implica que las clases derivadas deberían poder ser sustituidas por sus clases base. Es decir, es en cierto modo una extensión del principio anterior: mientras que OCP promueve la herencia de clases base, LSP promueve que la herencia se haga de forma transparente, es decir, que heredar es bueno pero no hay que olvidar las raíces. Es decir, no implementemos un método en una clase heredada que no esté en la clase base porque romperemos este principio.

De OCP y LSP se deduce que las clases base (abstractas o no) modelan el aspecto general y las clases heredadas modelan el comportamiento local.

DIP: Dependency Inversion Principle:
Básicamente, el principio de inversión de dependencia promueve que hay que depender de abstracciones, no de concreciones. Dicho de forma más compleja, los módulos de más alto nivel no deben depender de los de más bajo nivel sino que ambos deben depender de abstracciones. Y a su vez, las abstracciones no deben depender de los detalles sino al contrario.

En este caso, el uso de interfaces resulta muy beneficioso y un framework de inversión de control (Castle Windsor, StructureMap, por citar algunos) van a hacer que resulte más obvia la necesidad de abstracciones. Además, el testado unitario resulta mucho más sencillo ya que la independencia entre los distintos módulos es muy elevada.

ISP: Interface Segregation Principle:
Este principio de segregación de interfaces indica que no se debe hacer depender las clases de interfaces que no necesitan y que debe haber granularidad en las interfaces para dotar de aspectos específicos a las distintas implementaciones.

En general, en Java y C# se pueden implementar tantos interfaces como se quiera por lo que es sencillo llevar a cabo este principio. Las interfaces son la forma más práctica de modelar las clases y dotarlas de aspectos particulares así como incluso tratarlas de diferente modo según las interfaces implementadas.

Y estos son básicamente los principios SOLID que aunque llevan ya muchos años siguen siendo vigentes y ayudan a desarrollar un código más reusable, mantenible y claro. Además, con las herramientas actuales de refactorización es muy fácil extraer interfaces y clases abstractas de las ya existentes sin tener que revisar cientos de líneas de código. Y cómo no, tener un buen conjunto de tests unitarios ayudará a que cualquier refactorización se haga sin miedo a romper toda la funcionalidad existente.

Referencias: Principles of OOD

Posted in Programación | Tagged , , | 7 Comments

Apache y Mongrel en Windows

Después de pelear un rato intentando hacer funcionar Ruby on Rails con Apache y Fast-CGI en Windows, me iba bastante más lento que directamente con Mongrel, así que opté por usar este último y hacer un proxy vía Apache con mod_proxy.

Mongrel es bastante fácil de instalar, simplemente se hace un

gem install mongrel

y cuando pide la versión a seleccionar hay que seleccionar la de x86-mswin32.

Para ver si funciona, hay que ir a la carpeta donde está instalada nuestra aplicación Rails y ejecutar

mongrel_rails start

que iniciará el servicio en el puerto 3000 y nos dirá si hay algún error.

Una vez comprobado que Mongrel funciona, hay que instalarlo como servicio de Windows, por simple comodidad. Para ello hay que ejecutar

gem install win32-service

, que además nos instalará una serie de paquetes relacionados con Windows. Seleccionar siempre la versión x86-mswin32 si está disponible.

Ya está todo listo para instalar el servicio. Con el siguiente comando:

mongrel_rails service::install -N AplicacionRails -c RutaDeLaAplicacion -p 3001 -e production --prefix=/subdir

El nombre de la aplicación, en el parámetro -N es la que saldrá en el listado de servicios de Windows. Lo que va en el parámetro -c es la ruta de la aplicación Rails (no la carpeta public, sino la raíz). Luego se indica el puerto en -p (recomiendo que no sea 3000 para no entrar en conflicto si ejecutamos Mongrel independientemente). En el parámetro -e se indica el entorno, en principio “production” y finalmente y lo más importante, en –prefix se indica la subcarpeta donde se va alojar, es decir, si va a ser localhost/subdir, el valor deberá ser /subdir. Esto es sumamente importante para que funcione bien el proxy de Apache. Si va a estar en la raíz, no hace falta poner nada.

En cuanto a la configuración de Apache, tengo algo más o menos así en httpd.conf:

ProxyRequests off
ProxyPass /subdir http://localhost:3001/subdir
ProxyPreserveHost on

&lt;Location /subdir&gt;
   ProxyPassReverse /
&lt;/Location&gt;

Eso sí, hay que tener mod_proxy activado y mod_rewrite también (seguro que lo usa el .htaccess de la aplicación Rails).

Y esto es todo, así conseguí configurar el Redmine en Windows con Apache. Lo que más costó fue descubrir el parámetro –prefix de Mongrel para que alojase la aplicación en un subdirectorio, no soy ningún experto en Rails.

Espero que os sirva de ayuda.

Links:

Posted in Programación | Tagged , , | 1 Comment