Trabajando en un proyecto en este momento y tenemos que implementar una eliminación suave para la mayoría de los usuarios (roles de usuario). Decidimos agregar un campo "is_deleted = '0'" en cada tabla de la base de datos y establecerlo en '1' si roles de usuarios particulares presionan un botón de eliminación en un registro específico.
Para el mantenimiento futuro ahora, cada consulta SELECT deberá asegurarse de que no incluyen registros donde is_deleted = '1'.
¿Existe una mejor solución para implementar la eliminación suave?
Actualización: también debo tener en cuenta que tenemos una base de datos de auditoría que rastrea los cambios (campo, valor anterior, valor nuevo, tiempo, usuario, ip) a todas las tablas/campos dentro de la base de datos de la aplicación.
Puede realizar todas sus consultas en una vista que contiene el WHERE IS_DELETED='0'
cláusula.
Me inclinaría hacia un deleted_at
columna que contiene el fecha y hora de cuando se realizó la eliminación. Luego obtienes un poco de metadatos gratuitos sobre la eliminación. Para su SELECT
solo obtenga filas WHERE deleted_at IS NULL
Teniendo is_deleted
columna es un enfoque razonablemente bueno. Si está en Oracle, para aumentar aún más el rendimiento, recomendaría particionar la tabla creando una partición de lista en is_deleted
columna. Luego, las filas eliminadas y no eliminadas estarán físicamente en diferentes particiones, aunque para usted será transparente.
Como resultado, si escribe una consulta como
SELECT * FROM table_name WHERE is_deleted = 1
entonces Oracle realizará la 'poda de partición' y solo buscará en la partición apropiada. Internamente, una partición es una tabla diferente, pero es transparente para usted como usuario: podrá seleccionar en toda la tabla sin importar si está particionada o no. Pero Oracle podrá consultar SOLO la partición que necesita. Por ejemplo, supongamos que tiene 1000 filas con is_deleted = 0
y 100000 filas con is_deleted = 1
, y particiona la tabla en is_deleted
. Ahora si incluye condición
WHERE ... AND IS_DELETED=0
entonces Oracle SOLAMENTE escaneará la partición con 1000 filas. Si la tabla no estuviera particionada, tendría que escanear 101000 filas (ambas particiones).
La mejor respuesta, lamentablemente, depende de lo que intente lograr con sus eliminaciones suaves y la base de datos en la que está implementando esto.
En SQL Server, la mejor solución sería utilizar una columna deleted_on/deleted_at con un tipo de SMALLDATETIME o DATETIME (dependiendo de la granularidad necesaria) y hacer que esa columna sea anulable. En SQL Server, los datos del encabezado de la fila contienen una máscara de bits NULL para cada una de las columnas de la tabla, por lo que es marginalmente más rápido realizar un IS NULL o IS NOT NULL de lo que es verificar el valor almacenado en una columna.
Si tiene un gran volumen de datos, querrá examinar la partición de sus datos, ya sea a través de la base de datos o a través de dos tablas separadas (por ejemplo, Productos y Historial de productos) o mediante una vista indizada.
Por lo general, evito los campos de marca como is_deleted, is_archive, etc. porque solo tienen un significado. Un campo nullable deleted_at, archived_at proporciona un nivel adicional de significado para usted y para quien herede su aplicación. Y evito los campos de máscara de bits como la peste, ya que requieren una comprensión de cómo se construyó la máscara de bits para captar cualquier significado.
si la tabla es grande y el rendimiento es un problema, siempre puede mover los registros 'eliminados' a otra tabla, que tiene información adicional como el momento de la eliminación, quién eliminó el registro, etc.
de esa manera no tiene que agregar otra columna a su tabla primaria
Eso depende de qué información necesita y qué flujos de trabajo desea admitir.
¿Quieres ser capaz de:
Si el registro se eliminó y se eliminó cuatro veces, ¿es suficiente que sepa que actualmente se encuentra en un estado no eliminado o desea saber qué sucedió en el ínterin (incluidas las ediciones entre sucesivas eliminaciones!)?
Cuidado con los registros eliminados temporalmente que causan violaciones de restricciones de unicidad Si su base de datos tiene columnas con restricciones únicas, tenga cuidado de que los registros eliminados temporalmente no le impidan volver a crear el registro.
Piensa en el ciclo:
La segunda creación da como resultado una violación de restricción porque login = JOE ya está en la fila eliminada temporalmente.
Algunas técnicas: 1. Mueva el registro eliminado a una nueva tabla. 2. Establezca su restricción de unicidad en el inicio de sesión y la columna delete_at timestamp
Mi propia opinión es +1 para pasar a una nueva mesa. Se necesita mucha disciplina para mantener * AND delete_at = NULL * en todas sus consultas (para todos sus desarrolladores)
Definitivamente tendrá un mejor rendimiento si mueve sus datos eliminados a otra tabla, como dijo Jim, además de tener un registro de cuándo se eliminó, por qué y por quién.
Añadiendo where
deleted
= 0</code> para todas sus consultas, las ralentizará significativamente y obstaculizará el uso de cualquiera de los índices que pueda tener en la tabla. Evite tener "banderas" en sus tablas siempre que sea posible.
no menciona qué producto, pero SQL Server 2008 y postgresql (y otros, estoy seguro) le permiten crear índices filtrados, por lo que podría crear un índice de cobertura donde is_deleted = 0, mitigando algunos de los aspectos negativos de este enfoque en particular .
Algo que utilizo en los proyectos es statusInd tinyint no es nulo, la columna 0 predeterminada que usa statusInd como máscara de bits me permite realizar la gestión de datos (eliminar, archivar, replicar, restaurar, etc.). Usando esto en vistas, puedo hacer la distribución de datos, publicación, etc. para las aplicaciones consumidoras. Si el rendimiento es una preocupación con respecto a las vistas, utilice pequeñas tablas de hechos para respaldar esta información, descartando el hecho, descarta la relación y permite eliminaciones escalonadas.
Escala bien y se centra en los datos, manteniendo la huella de datos bastante pequeña: clave para 350 gb + dbs con preocupaciones en tiempo real. El uso de alternativas, tablas y desencadenantes tiene algunos gastos generales que, dependiendo de la necesidad, pueden o no funcionar para usted.
Las auditorías relacionadas con SOX pueden requerir más de un campo para ayudar en su caso, pero esto puede ayudar. Disfrutar
use una vista, función o procedimiento que verifique is_deleted = 0, es decir, no seleccione directamente en la tabla en caso de que la tabla deba cambiar más tarde por otros motivos
e indexe la columna is_deleted para tablas más grandes
como ya tiene una pista de auditoría, el seguimiento de la fecha de eliminación es redundante
Prefiero mantener una columna de estado, por lo que puedo usarla para varias configuraciones diferentes, es decir, publicada, privada, eliminada, necesita aprobación ...
Cree otro esquema y concédale todo en su esquema de datos. Implante VPD en su nuevo esquema para que todas y cada una de las consultas tengan el predicado que permita la selección de la fila no eliminada solo añadida. http://download.Oracle.com/docs/cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345
@AdditionalCriteria ("this.status <> 'eliminado'")
pon esto encima de tu @entity