En Internet hay miles de artículos sobre optimización de código y mejoras de escalabilidad para que tu super servicio soporte más de 10.000 peticiones por segundo. Y miles de programadores, en este momento, están leyendo esos artículos. Solía decir que de esos miles de ávidos lectores, en un momento dado, sólo dos realmente necesitan la información. Es decir, está bien optimizar pero cuando sabes que lo vas a necesitar, no por practicar otro deporte de riesgo. Sigo pensando así. Mi webapp, mi site, mi servicio de alquiler de mascotas por horas, no va a necesitar grandes alharacas en el terreno de la escalabilidad.
Hasta que descubres un nuevo problema de escalabilidad: el Señor Verde. En la biblioteca. Con un tablet. Traduciendo para los que no conocen el Cluedo: un único usuario con una tableta. Y su aplicación de CRM. O de cualquier otro sistema que tenga que machacar datos. Muchos datos. Un único usuario, no 10.000.
Independientemente de si la estructura de datos es de nueva planta o es una adaptación de un megadatawarehouse mantenido por tres ingenieros nucleares y dos consultores de la NASA lo que está claro es que, en algún momento, esa estructura va a dar problemas. De complejidad y, por lo tanto, de velocidad. La velocidad. El talón de Aquiles de cualquier tableta. Y el talón, el femur, la rabadilla y el brazo izquierdo de Aquiles de cualquier webapp en una tableta.
SQLite puede ejecutar los mismos queries que tu app contra un servidor Oracle. En una aplicación de escritorio la diferencia de velocidad no llega a afectar a la experiencia del usuario. Es en una tableta donde esta diferencia si se nota. No en el uso normal, buscando, mostrando resultados (donde si se mira el profiler con atención se ve que aún hay mucho por optimizar en el dibujado antes de meterse con los datos), sino en algunos momentos delicados. Por ejemplo, preparando una vista que muestra información de distintas subentidades. O en el, cada vez más requerido, dashboard o panel de control. Un sitio donde se tiende a obtener KPIs agrupando datos dispares. Ejecutando queries complejos. A veces muy complejos. Que puede que no tarden más de 1500ms en ejecutarse pero… uno detrás de otro + ejecutados en un entorno síncrono + uniendo el resultado de subqueries para obtener una cifra x cada vez que se redibuja el dashboard = lentitud percibida por el usuario.
Uno de los remedios típicos en web ha sido desnormalizar los datos, tunearlos para que los resultados sean lo más rápido posibles, a costa de aumentar el espacio que ocupan los datos. En un entorno donde el espacio es “barato” y la velocidad “cara” es normal que, por ejemplo, las relaciones de un usuario de un site social no se calculen a la hora de mostrarlas, sino que estén precalculadas y que lo que se muestra es el resultado de dicho cálculo.
¿Cómo podemos aprovecharnos de este truco en una aplicación (mixta o nativa) que usa SQLite o algún otro motor de datos en una tableta? Exactamente de la misma manera. Siguiendo con el ejemplo del CRM y del dashboard que muestra, por ejemplo, la desviación a la hora de conseguir un objetivo el sistema tradicional nos dicta que hemos de ejecutar uno o varios queries hasta obtener el número de elementos que se desvían del objetivo previsto en tal o cual grado. Siguiendo con ese sistema tradicional se ejecutan dichos queries contra todas las tablas implicadas en el cálculo de los KPIs. Para ponerlo claro: quiero el total de todos los pedidos que contengan líneas de productos que están en una tabla de promociones que se basan en la fecha y la situación geográfica del comprador que no lleguen a un mínimo de unidades y lo quiero agrupado por medio: presencial, teléfono o fax. Este sencillo query se ejecuta cada vez que se actualiza el dashboard como resultado de un cambio en los datos.
La opción no-tradicional puede ser tener una o más tablas específicas para el cálculo del resultado final. A la hora de crear o modificar un registro que afecta a la desviación, se calcula el valor para cada línea de pedido y, con el cálculo de estas, para el pedido. Se asigna, por ejemplo, un valor tipo y un valor si/no. Cuando se actualiza el dashboard ya no se ejecutan los queries para calcular el total de pedidos, sino que el query es sencillo y rápido. El “peso” del cálculo se ha llevado a un punto de la ejecución del programa, la grabación, donde el usuario puede esperar medio segundo más. Sólo se calculan las filas necesarias en la estructura de datos, no se ejecuta un query que busca determinadas líneas de los pedidos y luego cruza con los tipos de los pedidos.
Es un breve ejemplo de cómo luchar contra el problema definitivo de optimización y escalabilidad: Un usuario. En la biblioteca. Con un tablet.