El escenario es que tengo un conjunto de usuarios en expansión, y a medida que pasa el tiempo, los usuarios cancelarán sus cuentas que actualmente marcamos como 'eliminadas' (con un indicador) en la misma tabla.
Si los usuarios con la misma dirección de correo electrónico (así es como los usuarios inician sesión) desean crear una cuenta nueva, pueden registrarse nuevamente, pero se crea una cuenta NUEVA. (Tenemos identificadores únicos para cada cuenta, por lo que las direcciones de correo electrónico pueden duplicarse entre las en vivo y las eliminadas).
Lo que he notado es que en todo nuestro sistema, en el curso normal de las cosas, consultamos constantemente la tabla de usuarios para verificar que el usuario no se elimine, mientras que lo que estoy pensando es que no necesitamos hacer eso en absoluto ... ! [Aclaración1: por 'consultar constantemente', quise decir que tenemos consultas que son como: '... DE usuarios DONDE está eliminado = "0" Y ...'. Por ejemplo, es posible que tengamos que buscar a todos los usuarios registrados para todas las reuniones en una fecha en particular, por lo que en ESA consulta, también tenemos usuarios de FROM WHERE isdeleted = "0": ¿esto aclara mi punto?]
(1) continue keeping deleted users in the 'main' users table
(2) keep deleted users in a separate table (mostly required for historical
book-keeping)
¿Cuáles son los pros y los contras de cualquiera de los enfoques?
fuente
Respuestas:
Puede utilizar, por ejemplo, un activador para mover automáticamente a los usuarios eliminados a la tabla de historial.
fuente
Recomiendo usar la misma tabla. La razón principal es la integridad de los datos. Lo más probable es que haya muchas tablas con relaciones dependiendo de los usuarios. Cuando se elimina un usuario, no desea dejar esos registros huérfanos.
Tener registros huérfanos hace que sea más difícil hacer cumplir las restricciones y hace que sea más difícil buscar información histórica. El otro comportamiento a tener en cuenta es cuando un usuario proporciona un correo electrónico usado si desea que recupere todos sus registros antiguos. Esto funcionaría automáticamente mediante la eliminación suave. En cuanto a la codificación, por ejemplo, en mi aplicación actual de c # linq, la cláusula where deleted = 0 se agrega automáticamente al final de todas las consultas
fuente
Esto me da un mal olor a diseño. Deberías ocultar ese tipo de lógica. Por ejemplo, debe
UserService
proporcionar un métodoisValidUser(userId)
para usar "en todo el sistema", en lugar de hacer algo como:Su forma de almacenar usuarios eliminados no debería afectar la lógica empresarial.
Con este tipo de encapsulación, el argumento anterior ya no debería afectar el enfoque de su persistencia. Entonces puede concentrarse más en los pros y los contras relacionados con la persistencia misma.
Las cosas a considerar incluyen:
Normalmente tomaría una forma combinada:
fuente
Para responder adecuadamente a esta pregunta, primero debe decidir: ¿Qué significa "eliminar" en el contexto de este sistema / aplicación?
Para responder a esa pregunta, debe responder otra pregunta más: ¿por qué se eliminan los registros?
Existen varias buenas razones por las cuales un usuario podría necesitar eliminar datos. Por lo general, encuentro que hay exactamente una razón (por tabla) por la cual una eliminación podría ser necesaria. Algunos ejemplos son:
También hay algunas razones muy pobres para la eliminación forzada (más sobre las razones para esto más adelante):
¿Por qué, preguntas, es realmente tan importante? ¿Qué hay de malo con el bueno
DELETE
?Entonces, la eliminación suave es mejor, ¿verdad? No en realidad no:
La verdad es que ambos enfoques están equivocados. Eliminar está mal. Si realmente está haciendo esta pregunta, significa que está modelando el estado actual en lugar de las transacciones. Esta es una mala, mala práctica en tierra de bases de datos.
Udi Dahan escribió sobre esto en Don't Delete - Just Don't . Hay siempre algún tipo de tarea, transacción, la actividad , o (mi término preferido) evento que en realidad representa el "borrado". Está bien si posteriormente desea desnormalizar en una tabla de "estado actual" para el rendimiento, pero hágalo después de haber definido el modelo transaccional, no antes.
En este caso tienes "usuarios". Los usuarios son esencialmente clientes. Los clientes tienen una relación comercial con usted. Esa relación no se desvanece simplemente porque cancelaron su cuenta. Lo que realmente está sucediendo es:
En todos los casos, es el mismo cliente y posiblemente la misma cuenta (es decir, cada renovación de cuenta es un nuevo acuerdo de servicio). Entonces, ¿por qué estás eliminando filas? Esto es muy fácil de modelar:
Eso es. Eso es todo al respecto. Nunca necesitas borrar nada. Lo anterior es un diseño bastante común que se adapta a un buen grado de flexibilidad, pero puede simplificarlo un poco; puede decidir que no necesita el nivel "Acuerdo" y simplemente hacer que "Cuenta" vaya a una tabla "Estado de cuenta".
Si una necesidad frecuente en su aplicación es obtener una lista de acuerdos / cuentas activas , entonces es una consulta (ligeramente) difícil, pero para eso están las vistas:
Y tu estas listo. Ahora tiene algo con todos los beneficios de las eliminaciones suaves pero ninguno de los inconvenientes:
El único problema que queda por abordar es el problema de rendimiento. En muchos casos, en realidad resulta no ser un problema debido al índice agrupado activado
AgreementStatus (AgreementId, EffectiveDate)
: hay muy poca búsqueda de E / S allí. Pero si alguna vez es un problema, hay formas de resolverlo, utilizando disparadores, vistas indexadas / materializadas, eventos a nivel de aplicación, etc.Sin embargo, no se preocupe por el rendimiento demasiado pronto: es más importante hacer que el diseño sea correcto, y "correcto" en este caso significa usar la base de datos de la manera en que se debe usar una base de datos, como un sistema transaccional .
fuente
Actualmente estoy trabajando con un sistema en el que todas las tablas tienen un indicador de borrado para la eliminación suave. Es la ruina de toda existencia. Rompe totalmente la integridad relacional cuando un usuario puede "borrar" un registro de una tabla, pero los registros secundarios que FK vuelve a esa tabla no se borran en cascada. Realmente hace que los datos de basura después de que pase el tiempo.
Por lo tanto, recomiendo tablas de historial separadas.
fuente
Romper la mesa en dos sería lo más lamentable que se pueda imaginar.
Estos son los dos pasos muy simples que recomendaría:
PD: ¡Perdón por la demora de varios meses en responder!
fuente
Si hubiera estado recuperando cuentas eliminadas cuando alguien regresa con la misma dirección de correo electrónico, habría seguido manteniendo a todos los usuarios en la misma tabla. Esto haría que el proceso de recuperación de la cuenta sea trivial.
Sin embargo, a medida que crea nuevas cuentas, probablemente sea más sencillo mover las cuentas eliminadas a una tabla separada. El sistema en vivo no necesita esta información, así que no la exponga. Como usted dice, hace que las consultas sean más simples y posiblemente más rápidas en conjuntos de datos más grandes. El código más simple también es más fácil de mantener.
fuente
No menciona DBMS en uso. Si tiene Oracle con la licencia adecuada, puede considerar dividir la tabla de usuarios en dos particiones: usuarios activos y eliminados.
fuente