Digamos que tengo una aplicación de base de datos relacional y un objeto "usuario" y un objeto "mensaje". Ahora quiero mostrar la cantidad de mensajes no leídos a este usuario.
¿Cuál es la mejor manera de archivar esto? ¿Introduzco un campo en el usuario y lo cuento si el usuario recibe un mensaje y lo disminuyo si lo lee? ¿O ejecuto una consulta cada vez para calcular el número de mensajes para el usuario que están marcados como no leídos?
Creo que el primer enfoque es más complicado y propenso a errores, pero funcionará mejor que el segundo enfoque.
¿Cómo se hace esto normalmente o cuál es el mejor enfoque?
Respuestas:
El mejor enfoque es probarlo primero sin un campo adicional, medir el rendimiento y si realmente resulta demasiado lento, intente optimizarlo. Esto podría significar cambiar a su primer enfoque utilizando un campo adicional, pero también debe considerar probar otras opciones, por ejemplo, poner un índice adicional en los campos combinados ("no leídos", "ID de usuario") en sus mensajes.
fuente
La solución del libro de texto según la teoría de la base de datos sería no tener valores en su base de datos que dependan de los valores de otros datos, porque estas son dependencias transitivas . Tener campos que son valores calculados basados en otros campos es una violación de la normalización, ya que conduce a información redundante.
Sin embargo, a veces difieren lo que dice el libro de texto y cuál es el método más práctico en la práctica. Contar el número de mensajes no leídos en cada página vista puede ser una operación bastante costosa. El almacenamiento en caché del número en la
user
tabla sería mucho mejor para el rendimiento. El costo sería que es posible que existan inconsistencias en la base de datos: es posible que un mensaje se elimine, agregue o lea sin recordar actualizar también el contador no leído.fuente
INSERT
oDELETE
. (OUPDATE
, para dar cuenta del cambio de propietario de un mensaje). Un buen DBMS hará la operación y ejecutará los disparadores en la misma transacción, por lo que sucederá todo o nada.El problema potencial es el rendimiento y aún no tiene un problema de rendimiento. Hay muchas cosas que puede hacer dependiendo de la base de datos de elección para manejar esto en la solución # 1: indexación, hardware, almacenamiento en caché, etc. Todo esto depende de la frecuencia con la que el usuario necesita obtener un recuento actual de mensajes no leídos. Muchas de estas opciones no requieren una codificación personalizada en el lado de la aplicación, por lo que puede implementarlas con un cambio de código o muy poco. Hace que sea más fácil crecer con la aplicación.
Una vez que un usuario se conecta / inicia sesión, obtener el recuento de la base de datos una vez no es tan malo. ¿Su aplicación mantendrá una lista constantemente actualizada de mensajes como el correo electrónico? Obtener un recuento no leído desde aquí no requiere otro viaje a la base de datos y, de todos modos, obtener nuevos mensajes va a hacer un viaje de db.
¿Viaja a la base de datos cada vez que se lee un mensaje para marcar el IsRead? campo es suficiente sin un nuevo cálculo de otro campo.
Con la solución n. ° 2 (mantener un recuento en un campo / en el disco), ¿necesitará una rutina para reconstruir / recalcular periódicamente este campo cuando haya un problema? Y siempre hay problemas. ¿Vas a envolver todo esto en una transacción? Cada vez que alguien le envía un mensaje a otra persona, podría fallar porque no puede actualizar el UnreadCount del usuario receptor debido a un bloqueo de la tabla Usuario. ¿O va a crear una tabla separada para este campo?
fuente
La forma en que lo haría sería ejecutando una consulta cada vez, es decir, su segundo enfoque. Solo asegúrese de agregar un índice en su tabla de mensajes en la columna que actúe como una clave externa a la tabla de usuarios para mejorar el rendimiento de su consulta.
Luego, como dice Doc, mida el rendimiento de este enfoque y luego podrá saber si necesita tomar un camino diferente.
fuente