Question

Nous travaillons actuellement sur un projet et nous devons implémenter la suppression logicielle pour la majorité des utilisateurs (rôles d'utilisateur). Nous avons décidé d'ajouter un & Quot; is_deleted = '0' & Quot; champ sur chaque table de la base de données et définissez-le sur '1' si des rôles d'utilisateur particuliers appuient sur un bouton de suppression d'un enregistrement spécifique.

Pour la maintenance future maintenant, chaque requête SELECT devra s’assurer qu’elles ne comprennent pas les enregistrements où is_deleted = '1'.

Existe-t-il une meilleure solution pour implémenter la suppression logicielle?

Mise à jour: il convient également de noter que nous disposons d’une base de données d’audit qui suit les modifications (champ, ancienne valeur, nouvelle valeur, heure, utilisateur, ip) de toutes les tables / champs de la base de données d’application.

Était-ce utile?

La solution

Vous pouvez effectuer toutes vos requêtes sur une vue contenant la WHERE IS_DELETED='0' clause.

Autres conseils

Je me pencherais vers & "Rails way &"; avec une colonne deleted_at contenant la date-heure du moment où la suppression a eu lieu . Ensuite, vous obtenez un peu de métadonnées gratuites sur la suppression. Pour votre SELECT juste obtenir des lignes WHERE deleted_at IS NULL

Avoir is_deleted la colonne est une bonne approche. Si c'est dans Oracle, pour augmenter encore les performances, je vous recommande de partitionner la table en créant une partition de liste sur la colonne is_deleted = 0. Ensuite, les lignes supprimées et non supprimées seront physiquement dans des partitions différentes, même si pour vous, elles seront transparentes.

Par conséquent, si vous tapez une requête telle que

SELECT * FROM table_name WHERE is_deleted = 1

alors Oracle effectuera le "découpage de la partition" et ne cherchera que la partition appropriée. En interne, une partition est une table différente, mais elle est transparente pour vous en tant qu’utilisateur: vous pourrez effectuer une sélection dans l’ensemble de la table, qu’elle soit partitionnée ou non. Mais Oracle pourra interroger UNIQUEMENT la partition dont il a besoin . Par exemple, supposons que vous avez 1000 lignes avec is_deleted = 1 et 100 000 lignes avec <=> et que vous partitionnez la table sur <=>. Maintenant, si vous incluez la condition

WHERE ... AND IS_DELETED=0

alors Oracle analysera UNIQUEMENT la partition avec 1000 lignes. Si la table n'était pas partitionnée, elle devrait analyser 101 000 lignes (les deux partitions).

si la table est volumineuse et que les performances posent problème, vous pouvez toujours déplacer les enregistrements "supprimés" vers une autre table, qui contient des informations supplémentaires telles que le temps de suppression, le nom de l'utilisateur qui a supprimé l'enregistrement, etc.

Ainsi, vous n'avez pas besoin d'ajouter une autre colonne à votre table primaire

La meilleure réponse, malheureusement, dépend de ce que vous essayez d'accomplir avec vos suppressions douces et de la base de données dans laquelle vous l'implémentez.

Dans SQL Server, la meilleure solution consisterait à utiliser une colonne delete_on / delete_at avec un type SMALLDATETIME ou DATETIME (selon la granularité requise) et à rendre cette colonne nullable. Dans SQL Server, les données d'en-tête de ligne contiennent un masque binaire NULL pour chacune des colonnes de la table. Il est donc légèrement plus rapide d'exécuter IS NULL ou IS NOT NULL que de vérifier la valeur stockée dans une colonne.

Si vous avez un volume de données important, envisagez de partitionner vos données, soit via la base de données elle-même, soit via deux tables distinctes (par exemple, Produits et ProductHistory) ou via une vue indexée.

J'évite généralement les champs d'indicateurs tels que is_deleted, is_archive, etc., car ils ne portent qu'un seul élément de signification. Un champ nullable delete_at, archived_at fournit un niveau de signification supplémentaire pour vous et pour quiconque hérite de votre application. Et j'évite les champs de masques de bits comme la peste, car ils nécessitent une compréhension de la construction du masque de bits afin de saisir tout sens.

Cela dépend des informations dont vous avez besoin et des workflows que vous souhaitez prendre en charge.

Voulez-vous pouvoir:

  • savez-vous quelles étaient les informations (avant leur suppression)?
  • savez-vous quand il a été supprimé?
  • savez-vous qui l'a supprimé?
  • savoir à quel titre ils agissaient lorsqu'ils l'ont supprimé?
  • pouvoir annuler la suppression de l'enregistrement?
  • être capable de dire quand il a été supprimé?
  • etc.

Si l’enregistrement a été supprimé et non supprimé à quatre reprises, est-il suffisant de savoir qu’il est actuellement dans un état non supprimé ou voulez-vous pouvoir savoir ce qui s’est passé entre-temps (y compris modifications entre les suppressions successives!)?

Attention aux enregistrements supprimés doucement qui entraînent des violations de contrainte d'unicité. Si votre base de données contient des colonnes avec des contraintes uniques, veillez à ce que les précédents enregistrements supprimés à l'aide d'un logiciel ne & # 8217; ne vous empêchent pas de recréer l'enregistrement.

Pensez au cycle:

  1. créer un utilisateur (login = JOE)
  2. soft-delete (définit la colonne supprimée sur une valeur non nulle.)
  3. créer (re) créer un utilisateur (login = JOE). ERREUR. LOGIN = JOE est déjà pris

La deuxième création entraîne une violation de contrainte car login = JOE se trouve déjà dans la ligne supprimée progressivement.

Quelques techniques:  1. Déplacez l’enregistrement supprimé vers une nouvelle table.  2. Faites votre contrainte d'unicité dans les colonnes de connexion et de timestamp delete_at

Mon opinion personnelle est +1 pour passer à une nouvelle table. Sa prend beaucoup de     discipline pour maintenir le * AND delete_at = NULL * dans tous vos     requêtes (pour tous vos développeurs)

Vous obtiendrez certainement de meilleures performances si vous déplacez vos données supprimées vers une autre table, comme l'a dit Jim, tout en conservant un enregistrement indiquant quand elles ont été supprimées, pourquoi et par qui.

L'ajout de where deleted = 0 à toutes vos requêtes les ralentira considérablement et entravera l'utilisation des index que vous pourriez avoir sur la table. Évitez d’avoir & Quot; flags & Quot; dans vos tables chaque fois que possible.

Quelque chose que j'utilise dans les projets est un statusInd tinyint not null null 0 column utiliser statusInd comme masque binaire me permet d'effectuer la gestion des données (suppression, archivage, réplication, restauration, etc.). En utilisant ceci dans les vues, je peux ensuite faire la distribution des données, la publication, etc. pour les applications consommatrices. Si les performances représentent un problème pour les vues, utilisez des petites tables de faits pour prendre en charge ces informations. Supprimez ce fait, supprimez la relation et autorisez les suppressions masquées.

Échelle bien et centré sur les données, ce qui permet de garder une empreinte de données relativement petite - clé pour 350 Go + dbs avec des préoccupations en temps réel. L'utilisation d'alternatives, de tables et de déclencheurs entraîne une surcharge qui, en fonction des besoins, peut ne pas fonctionner pour vous.

Les audits liés à SOX peuvent nécessiter plus d’un champ pour vous aider dans votre cas, mais cela peut aider. Profitez

vous ne mentionnez pas quel produit, mais SQL Server 2008 et postgresql (et d'autres j'en suis sûr) vous permettent de créer des index filtrés. Vous pouvez donc créer un index de couverture dans lequel is_deleted = 0, atténuant ainsi certains des points négatifs de cette approche particulière.

Je préfère conserver une colonne de statut afin de pouvoir l'utiliser pour plusieurs configs, à savoir publié, privé, supprimé, needAproval ...

utiliser une vue, une fonction ou une procédure vérifiant is_deleted = 0, c'est-à-dire ne sélectionnez pas directement sur la table au cas où celle-ci doit être modifiée ultérieurement pour d'autres raisons

et indexez la colonne is_deleted pour les tables plus volumineuses

puisque vous avez déjà une piste d'audit, le suivi de la date de suppression est redondant

Créez un autre schéma et accordez le tout sur votre schéma de données. Implémentez VPD sur votre nouveau schéma pour que chaque requête ait le prédicat permettant la sélection de la ligne non supprimée uniquement. http://download.oracle.com/docs /cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345

@AdditionalCriteria (& "; this.status < > 'supprimé" & ";))

mettez ceci au-dessus de votre @entity

http://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top