Ich baue eine Inventardatenbank auf, in der Computerausrüstung und andere Hardwaregeräte erfasst werden. Irgendwann im Leben eines Geräts wird es ausgemustert und archiviert. Nachdem es archiviert wurde, muss es nachverfolgt werden, wenn es außer Betrieb genommen und ordnungsgemäß entsorgt wird. Ich habe den Archivierungsmechanismus ursprünglich unter Verwendung einer exakten Replik der aktiven Datenbank entworfen, die ihre Daten mithilfe eines Auslösers beim Löschen aus der aktiven Datenbank empfangen würde. Die Archivdatenbank enthält Replikate aller zugehörigen Tabellen, da bestimmte fremdbezogene Datensätze nicht mehr relevant sind und für Benutzer mit neuen Geräten nicht zugänglich sein sollten, sondern für die referenzielle Integrität und die Abfrage mit den Archivtabellen erforderlich sind. Denken Sie daran, dass das Konzept des Archivs hier nicht nur darin besteht, einen Verlauf oder ein Protokoll zu führen. Das Archiv ist Teil des Geschäftsprozesses.
Die folgende ERD verwendet die Inventory.DeviceType
Tabelle als Beispiel, in der alle Einträge und Aktualisierungen in die Archive.DeviceType
Tabelle kopiert werden. Wenn Benutzer keine Inventardatensätze eines bestimmten Gerätetyps mehr eingeben können, werden diese aus der Inventory.DeviceType
Tabelle gelöscht , verbleiben jedoch in der Archivtabelle. Dieses Muster wird für alle Tabellen verwendet, um sicherzustellen, dass die Archive auf gültige Daten verweisen, daher die Replik aller Tabellen.
Beispiel für eine aktive Tabelle (andere verwandte Tabellen weggelassen)
Beispiel für eine Archivtabelle (andere verwandte Tabellen weggelassen)
Problem
Ich versuche herauszufinden, wie ich die Datenbank abfragen würde, wenn ich nicht weiß, ob ein Gerät aktiv oder archiviert ist. Zum Beispiel, wenn ein Benutzer eine Seriennummer hat und Informationen über das Gerät herausfinden möchte und nicht weiß, ob es archiviert wurde.
Option 1: Erstellen Sie eine Ansicht basierend auf einer Union all?
Option 2: Die aktive Datenbank abfragen und dann das Archiv abfragen, wenn die erste Abfrage nichts zurückgibt?
Die Saga geht weiter ...
Ein Mitarbeiter schlug vor, die Archivdatenbank zu entfernen und ein Soft-Delete-Schema zu verwenden. Mit dieser Idee baute ich ein Modell und stieß dann auf eine Reihe anderer Probleme.
Hier sind die gleichen Tabellen, die das Soft-Delete-Schema verwenden.
Beispiel für weiches Löschen
Bei diesem Setup werden Geräte archiviert, indem das IsArchived
Feld auf true gesetzt und ein eingegeben wird ArchivedDate
. Ich könnte jedes Gerät leicht abfragen, ob es aktiv oder archiviert ist. (Bitte ignorieren Sie das IsActive
Feld, da dies für ein nicht verwandtes Konzept verwendet wird.)
Beachten Sie die Subtyp-Tabelle "Telefon", in der ich einen Index der Geräte-ID und des IsArchived-Flags weitergeben musste, da Telefonnummern für aktive Geräte eindeutig sein müssen. Ich muss dies auch mit anderen Subtyp-Tabellen tun. Ich weiß nicht, ob dies ein gutes oder ein schlechtes Design ist.
Dieser Teil verwirrt mich wirklich ...
Was sind Best Practices für den Umgang mit weichen Löschvorgängen, bei denen Fremdschlüsselwerte als gelöscht markiert werden können? Ich kann mir nur vorstellen, eine Routine zu erstellen, die nach allen Datensätzen sucht, die sich auf gelöschte Daten beziehen, und einen Bericht für Benutzer zu erstellen, um die Diskrepanzen zu beheben. Wenn beispielsweise eine Standorttabelle mit der Gerätetabelle verknüpft ist und einige Standorte weich gelöscht werden, beziehen sich die Geräte auf Standorte, die nicht mehr vorhanden sind und verschoben werden müssen.
Übrigens verwende ich MS SQL Server 2008 R2 und plane, Entity Framework 4 in meiner Anwendung zu verwenden. Ich schätze die Wartbarkeit der Datenbank gegenüber der Leistung.
Danke fürs Lesen.
quelle
Antworten:
Ich würde sagen, wenn Ihre Benutzer die Archivdaten abfragen müssen, ist die Verwendung des
bit
Flags odersoft delete
einfacher. Wenn die Benutzer die Daten nicht mehr benötigen, würde ich mit den Archivtabellen gehen.Basierend auf Ihrer obigen Beschreibung würde ich vorschlagen, mit der
Soft Delete
Version zu gehen. Ich kann Ihnen aus Erfahrung in einem unserer Systeme sagen, dass wir ein Archivschema verwendet haben, um ältere Daten zu verschieben, und dies führte nur zu Problemen, da die Benutzer Zugriff auf die Daten benötigten. Dies führte dazu, dassUNION ALL
jede Abfrage verwendet wurde, die wir ausführen mussten.Aufgrund der Probleme haben wir diese Route gestoppt und sind zum weichen Löschen übergegangen, was viel einfacher ist.
Wir haben
bit
allen benötigten Tabellen ein Flag hinzugefügt und dieses dann bei derWHERE
Abfrage der Daten einfach in die Klausel aufgenommen.Ein Vorschlag wäre, sicherzustellen, dass dieses Feld einen Standardwert hat, wenn Sie
INSERT
Daten. Wenn Sie verwenden,IsArchived
ist der Standardwert für die Spalte false, da Sie nicht möchten, dass er sofort archiviert wird.quelle
Ich habe mich in letzter Zeit selbst mit der Frage von Soft Delete gegen Archivtabellen auseinandergesetzt, und offensichtlich gibt es im Web viele Artikel mit der Aufschrift "Nicht Soft Delete, Archiv". Ich habe noch keinen Archivanwalt gefunden, der sogar anerkennt, dass Ihr Problem besteht, aber ich glaube, ich habe herausgefunden, warum.
Es geht um zwei Gründe, warum eine Tabelle das PK-Ende eines Fremdschlüssels sein kann: weil sie die Daten in der anderen Tabelle logisch besitzt oder weil es sich um Referenzen handelt. Ein Auftrag "besitzt" seine Bestelldetails. Eine Adresse verweist lediglich auf einen Staat.
Wenn alle FKs, die auf eine Tabelle verweisen, "im Besitz" von Beziehungen sind, sollten Sie nicht sanft löschen.
Ihre DeviceTypes werden von Devices referenziert und gehören nicht dazu. Das Archivmuster funktioniert hier nicht, es behindert die Durchsetzung der referenziellen Integrität.
Hier ist jedoch die Sache: Das Absetzen eines Gerätetyps ist logischerweise kein Löschen. Die Daten sind immer noch live in dem Sinne, dass sie von Geräten referenziert werden. Sie können einen verwendeten Gerätetyp (logisch) nicht löschen. Da Ihre logische Operation kein Löschen ist, ist Ihre Verwendung des NotAvailable-Flags eigentlich kein weiches Löschen. Ich denke, deshalb sprechen die Befürworter des Archivs das nicht an.
In meinem Fall habe ich mich für Archivtabellen entschieden, weil ich Daten wirklich logisch löschen, aber nur zu Überwachungszwecken aufbewahren möchte. Der Grund für meine Wahl hatte jedoch nichts mit der Datenbank zu tun. Da EntityFramework Soft-Löschvorgänge nicht gut unterstützt, konnte ich keine gute Möglichkeit finden, sie für Navigationseigenschaften durchzusetzen.
In SQL Server 2008 R2 können Sie die meisten Nachteile abschwächen, die Archivanwälte für Soft Deletes geltend machen. Sie können gefilterte Indizes verwenden, um die Leistungseinbußen beim Tragen einer Reihe gelöschter Datensätze in Ihrer Tabelle zu verringern (und das sanfte Löschen ist weitaus billiger als das Archivieren, es sei denn, Sie partitionieren Ihre Tabelle, was für die Sicherungsstrategie möglicherweise sinnvoll ist ). Ich glaube, Sie können die referenzielle Integrität auch für das Löschflag erzwingen, indem Sie sich an eine Technik halten, die ich einmal in einem Celko-Artikel gesehen habe- Untergeordnete Tabellen können ein ParentIsDeleted-Flag und zwei FKs für ihre übergeordneten Tabellen haben, eine nur für ParentId, die andere für ParentId und ParentIsDeleted. Sie könnten sogar ParentIsDeleted, SelfIsDeleted haben und IsDeleted zu einem persistierten berechneten Feld machen, damit Undelete direkte Löschungen von untergeordneten Löschungen von Löschungen unterscheiden kann, die vom übergeordneten Element kaskadiert werden. Für Sie löschen Sie jedoch nicht wirklich und möchten die Nichtverfügbarkeit eines Gerätetyps, für den Geräte vorhanden sind, nicht verhindern oder kaskadieren.
quelle
Sie können die Schlüsseltabellen nach einer Kombination aus der primären ID und dem IsArchived-Flag partitionieren. Dies hätte den doppelten Vorteil, Abfragen zu vereinfachen und die Leistung von Abfragen usw. gegenüber nicht archivierten Datensätzen aufrechtzuerhalten.
quelle