¿Existen pautas o reglas generales para determinar cuándo almacenar valores agregados y cuándo calcularlos sobre la marcha?
Por ejemplo, supongamos que tengo widgets que los usuarios pueden calificar (ver el esquema a continuación). Cada vez que visualizo un widget, puedo calcular la calificación promedio de los usuarios de la Ratings
tabla. Alternativamente, podría almacenar la calificación promedio en la Widget
mesa. Esto me evitaría tener que calcular la calificación cada vez que visualizo el widget, pero luego tendría que volver a calcular la calificación promedio cada vez que un usuario calificara un widget.
Ratings Widgets
--------- -------
widget_id widget_id
user_id name
rating avg_rating <--- The column in question
Con qué frecuencia necesita calcular / mostrar los valores relativos a la frecuencia con la que se cambian / actualizan los números subyacentes.
Entonces, si tiene un sitio web con 10k visitas diarias que muestra un valor que solo cambiará una vez por hora, lo calcularía cuando cambien los valores subyacentes (podría ser un desencadenante de la base de datos, lo que sea).
Si tiene una herramienta para ver las estadísticas, donde las estadísticas cambian por segundo, pero solo tres personas tienen acceso, y solo lo miran un par de veces al día, es más probable que calcule sobre la marcha. (a menos que, tome un par de minutos calcular que haber tenido datos obsoletos en primer lugar no es gran cosa ... y mi jefe me dice que genere la cosa desde cron cada hora, por lo que no tiene esperar cuando quiera mirarlo.)
fuente
Utilice la tabla StaleWidgets como una cola de widgets "no válidos" (para ser recalculados). Utilice otra tarea de subproceso (asíncrono) que pueda volver a calcular estos valores. El período o momento de recálculos depende de los requisitos del sistema:
fuente
Sugeriría que calcule sobre la marcha si el cálculo no es demasiado engorroso y en el caso de que tenga cálculos complejos y actualizaciones frecuentes, pero no esa lectura de frecuencia que puede almacenar datos calculados y tener una columna adicional (bool) que almacenará si se requiere un recálculo o no . por ejemplo, establezca esta columna en verdadero siempre que se deba realizar el recálculo, pero no realice el recálculo y cuando realice el recálculo, establezca esta columna como falsa (esto representará que el valor calculado es el último y no está obsoleto).
De esta manera, no tiene que volver a calcular cada vez, solo calculará cuando tenga que leer y el valor de la columna de recálculo sea verdadero. De esta manera, ahorrará muchos recálculos.
fuente
Para el caso en particular, existe una solución diferente en la que no tiene que agregar todas las calificaciones y dividirlas por el total para encontrar el promedio. En cambio, puede tener otro campo que contenga el total de las revisiones, por lo tanto, cada vez que agrega una calificación, calcula el nuevo promedio usando (avg_rating × total + new_rating) / total, esto es mucho más rápido que el agregado y reduce las lecturas del disco ya que no tiene que acceder a todos los valores de calificación. Soluciones similares podrían aplicarse a otros casos.
La desventaja de esto es que no es una transacción ácida, por lo que puede terminar con una calificación desactualizada. Pero aún así puede resolverlo utilizando desencadenantes en la base de datos. El otro problema es que la base de datos ya no está normalizada, pero no tenga miedo de desnormalizar los datos a cambio del rendimiento.
fuente