Mi dilema de hoy. Cambiar o no el diseño?
Desde hace un tiempo estoy con un desarrollo de un sistema de consultas web. Maneja un volumen importante de datos pues incorpora unos 1.300.000 registros con muchos datos nuevos al año y va a tener almacenados varios años.
Dentro de los requerimientos del mismo es que las consultas sean muy ágiles y que se soporte varios usuarios en forma simultanea, por lo que para lograr buena performance decidí utilizar tablas que acumulen los datos, para resolver todas las consultas pesadas en el momento de cargar los datos.
Para esto, llegue a una solución con 8 tablas, que tenían todas las combinaciones posibles de las consultas que se podían realizar.
El tener tantas tablas acumuladas, implico que tenia que usar varios Data Providers y Data selectors para lograr resolver las consultas.
El desarrollo ya esta bastante avanzado y probado, pero aun no esta en producción. Todo esta funcionando bien, pero aun falta agregar parte de las funcionalidades necesarias.
En el día de ayer en la noche, se me ocurrió un diseño que permite resolver el mismo problema con solo una tabla, lo cual me permitiría tener muchos menos objetos y por lo tanto facilitar el mantenimiento posterior.
Que debo hacer?
Dentro de los requerimientos del mismo es que las consultas sean muy ágiles y que se soporte varios usuarios en forma simultanea, por lo que para lograr buena performance decidí utilizar tablas que acumulen los datos, para resolver todas las consultas pesadas en el momento de cargar los datos.
Para esto, llegue a una solución con 8 tablas, que tenían todas las combinaciones posibles de las consultas que se podían realizar.
El tener tantas tablas acumuladas, implico que tenia que usar varios Data Providers y Data selectors para lograr resolver las consultas.
El desarrollo ya esta bastante avanzado y probado, pero aun no esta en producción. Todo esta funcionando bien, pero aun falta agregar parte de las funcionalidades necesarias.
En el día de ayer en la noche, se me ocurrió un diseño que permite resolver el mismo problema con solo una tabla, lo cual me permitiría tener muchos menos objetos y por lo tanto facilitar el mantenimiento posterior.
Que debo hacer?
- Cambiar el diseño para simplificar mantenimiento en el futuro, aunque me de mucho mas trabajo ahora. Tengo que volver a programar y probar mucha cosa.
- Dejar el diseño actual, con lo cual posiblemente quede como definitivo lo cual me va a complicar el mantenimiento. Ademas complica un poco la administración de la base de datos pues hay mas tablas a controlar.
Si estuviese en el comienzo del proyecto, no dudaría en hacer y probar el nuevo diseño que es mas prometedor, pero a la altura que estoy, hacer el cambio puede atrasar todo el proyecto.
Si estuviese en producción creo que ni consideraría hacer el cambio, sino que lo plantearia para una nueva versión.
Seguramente haga una prueba básica con el nuevo diseño y luego defina.
Como creo que conozco de que sistema hablás y supongo cual puede ser la solución, me aventuro a opinar lo siguiente:
ResponderBorrarAnalizaría el volumen de datos que pasaría a tener la tabla única. Si actualmente tenés el volumen está distribuido entre varias tablas, tenés la ventaja de tener índices más chicos y menos índices por tabla. Mientras que unificando todas las tablas, necesitarías todos los datos y todos los índices en la misma tabla, haciendola más dificil de manejar y entorpeciendo las modificaciones de datos.
Ahora, si el volumen de datos de la tabla unificada es del mismo orden de magnitud que la mayor de las tablas actuales, entonces el incremento en volumen de datos no sería un problema. De todos modos analizaría el incremento en la cantidad de índices.
Y si estas cosas no te parecen una amenaza y ya tenés el sistema terminado supongo que lo más importante es pensar cuanto esfuerzo en mantenimiento y mejoras te puede ahorra el nuevo diseño.
Si todavía estás a tiempo => cambiar el diseño.
ResponderBorrarHola Enrique, lo que dice Pablo es muy cierto.
ResponderBorrarYo tendría en consideración ese tema.
Mencionaste "consultas web".
¿Es solo lectura o también tienes Escrituras y Sincronización entre las tablas?
Según el DBMS también tienes la opción de crear vistas indexadas, las cuales tienen algunas particularidades con respecto a los índices normales (algunos hint's internos para performance).
Prueba pegarle una ojeada al siguiente documento http://msdn.microsoft.com/en-us/library/cc917715.aspx
Con lo cual podrías programarte las vistas representando esas diferentes vistas que hoy tienes en tablas (implementando los cálculos en las sentencias select), ya que tienes muy claro cuáles son los accesos por lo que puedes crear algo performante adaptado a cada consulta (y lo bueno es que mantienes la lógica que tienes hoy en día programada en Genexus, solo que en vez de ser tablas son vistas, eliminando procesos de replicación).
Tengo poca información como para decirte "tal solución es mejora que la otra".
En la balanza hay 2 temas, por un lado el costo en mantenimiento (tu costo?) o problemas de escalabilidad (una única tabla).
Siempre existe la alternativa de encontrar la forma de automatizar ese costo en mantenimiento, ya que en el fondo la partición es una "visión" diferente de la consolidada.
Puede que malinterprete cual es el costo, en una de esas con lo de las vistas indexadas tu costo podría disminuir y al mismo tiempo lograr el tema de mejorar la performance.
Si es un SQLServer y estás usando Joins y consultas "complejas", tendrías que ver si no estás teniendo problemas con la tempdb.
Conozco casos de consultas complejas con necesidad de alta performance en las cuales montan la tempdb en memoria ram (montando ramdisk y remontando tempdb en ese sitio o usando "tempdb in RAM" una funcionalidad del SQLServer, busca en inter y encontrarás info.)
Siempre hay forma de encontrarle la vuelta, sin embargo el diseño original es importante.
Si nace "ya pensado para soportarlo" las otras herramientas te ayudarán al "tunning", pero si ya de prima es un mal diseño por más que existan trucos de performance no podrás esquivar el problema de una mala decisión inicial.
Mi opinión:
Es importe detectar el problema antes de puesta en producción (aceptarlo e invertir en refactoring corrigiéndolo con una buena base de argumentos), que encontrarlo en plena producción con el cliente en problemas... (Entrando en pánico sin posibilidad de "sobrevivir", ya que hay que tirar todo y volverlo a hacer,ad+ de tener el problema de algo ya en marcha).
Cambiar.
ResponderBorrarLos proyectos se atrasan por tantas “pavadas” que esta bueno que de vez en cuando se atrasen para dejar las cosas espectaculares.
Pablo: El sistema es similar al que trabajamos juntos.
ResponderBorrarEn cuanto al problema de analizar el volumen da datos, es algo que ya hice, y voy a tener unos 10 registros en la tabla acumulada por cada registro original, pues debo guardar varias combinaciones posibles. En cuanto a los indices, voy a tener pocos pero van a ser muy grandes.
Gracias por el comentario.
Marcos:
ResponderBorrarLo importante es definir si estoy a tiempo. Si hago el cambio, me voy a atrasar con la entrega. El cliente puede tolerarlo, pero todo el trabajo es a costo mio.
David:
ResponderBorrarDebi aclararlo de entrada, el sistema usa MySQL y tiene una actualizacion diaria, en un proceso batch, que debe actualizar todo lo necesario para que pueda consultarse.
La opcion de vistas indexadas (sql server), o de vistas materializadas (oracle) no son viables en este caso.
Por el volumen de datos, no creo que pueda tener grandes problemas de escalabilidad, pues estoy pensando que tendre unos 10 millones de registros en la tabla original y unos 100 millones en la tabla acumulada.
Como las sumas y la cuenta de registros se resuelven en la carga, las consultas van a tener que acceder a un solo registro para poder resolver la mayoría de las cosas.
En el peor de los casos, hay que mostrar rankings de unos 4000 elementos y deben mostrarse paginando, por lo que no hay mayor problema.
Por como es tu comentario, me da la sensación que entendiste que hay algún problema de performance, y con el diseño actual no lo tengo.
El cambiar el esquema de las 8 tablas, a la tabla única de acumulado, lo unico que me cambiaría seria que todo quedaría mas fácil de cambiar en el futuro, pues voy a tener menos objetos que mantener. En cuanto a performance, creo que va a ser similar.
Es un cambio, que el cliente tampoco vería, ni valoraría, pero a mi me dejaría mas contento, pues el codigo creo que va a quedar "mas lindo". O mejor dicho, no tendría el "olor feo" que le siento al código viejo cuando lo veo.
En fin, creo que voy a tener que seguir meditándolo.
Gracias por el comentario.
Andres:
ResponderBorrarAgradezco el empuje para seguir cambiando.
Si no tuviera que tirar lo que programe hace poco y esta funcionando no lo dudaria, pero como es algo que el cliente no entendera nunca, voy a meditarlo un poco...
Como psicólogo que soy y luego de leer el post + los comentarios, creo que estas esperando a alguien que te diga "dejalo así": dejalo así.
ResponderBorrarY ya que hay varias opciones , por qué no agregás la única tabla como una novena , y la actualizás en el batch ? Luego ponés una en producción una semana , y la otra semana probás con la otra , así durante un tiempo , y así generás tremenda base de experiencia para el futuro y ganás aunque el cliente no te lo pague.
ResponderBorrarAparte , sobre el olor feo de lo ya hecho , seguro alguna vez te pasó que con el tiempo algo que hiciste , luego lo viste feo , muy luego lo valoraste más, e incluso te ayudó a entender el problema desde más perspectivas.
Si se tratara de una aplicación CRUD full time (no sólo batch once a day) , no te sugeriría esto.
Que lastima que no tengas la libertad para decidir como queres hacerlo. :(
ResponderBorrarSuerte con lo que decidas.
Roberto:
ResponderBorrarTengo sentimientos encontrados, por un lado quiero dejarlo asi, por otro quiero cambiarlo.
Haroldo:
Lo que propones, es lo que estoy haciendo ahora, para comparar las dos opciones.
Una cosa que no dije, es que la opcion 1 (de 8 tablas) es desde el punto de vista teorico "mas correcta" pues usa todos campos claves que ya existen en la aplicacion. En la opcion 2 tuve que inventar una clave (concatenando campos de otras) que no es lo mas correcto, pero como dije antes, puede ser mejor desde el punto de vista del mantenimiento.
Andres:
El problema es que tengo libertad de elegir... y las dos opciones tienen pros y contras....
Tenés que hacer lo que te parezca correcto. Si la opc. de 1 tabla es la que más te gusta, seguramente si no lo haces ahora, apenas surja algún cambio en la aplicación vas a estar otra vez lamentandote por no haberlo cambiado antes de ponerlo en producción.
ResponderBorrarYo hew tenido dilemas similares en el desarrollo de aplicaciones, y nunca me he arrepentido de hacer lo que mejor me va a ir en el futuro (el dinero que "pierdas ahora" puedes recuperarlo en el futuro con mejor mantenimiento).
ResponderBorrarVe por la solución 2
Normalmente te diría que lo cambiaras. Pero hace poco leí este artículo que creo que aplica muy bien a tu situación:
ResponderBorrar7 reasons to hate your code
Por otro lado, un buen consejo: convertí el problema a plata. Cuanto gastas por hacer el cambio y cuanto potencialmente ganás, incluyendo intangibles. La plata en si misma puede no ser importante, pero es maravillosa para unificar unidades heterogeneas.