Das Szenario sieht so aus, dass immer mehr Benutzer angemeldet sind. Mit der Zeit kündigen Benutzer ihre Konten, die wir derzeit in derselben Tabelle als "gelöscht" (mit einem Flag) markieren.
Wenn Benutzer mit derselben E-Mail-Adresse (so melden sich Benutzer an) ein neues Konto erstellen möchten, können sie sich erneut anmelden, es wird jedoch ein NEUES Konto erstellt. (Wir haben eindeutige IDs für jedes Konto, sodass E-Mail-Adressen zwischen aktiven und gelöschten Adressen dupliziert werden können.)
Was mir aufgefallen ist, ist, dass wir im gesamten System ständig die Benutzertabelle abfragen, um sicherzustellen, dass der Benutzer nicht gelöscht wird. Ich denke jedoch, dass wir das überhaupt nicht tun müssen ... ! [Klarstellung1: Mit "ständigem Abfragen" meine ich, dass wir Fragen haben, die wie folgt lauten: "... FROM users WHERE isdeleted =" 0 "AND ...". Beispielsweise müssen wir möglicherweise alle Benutzer abrufen, die für alle Besprechungen an einem bestimmten Datum registriert sind. In DIESER Abfrage haben wir also auch FROM-Benutzer, bei denen isdeleted = "0" ist. Macht dies meinen Standpunkt klarer?]
(1) continue keeping deleted users in the 'main' users table
(2) keep deleted users in a separate table (mostly required for historical
book-keeping)
Was sind die Vor- und Nachteile beider Ansätze?
quelle
Antworten:
Sie können z. B. einen Trigger verwenden, um gelöschte Benutzer automatisch in die Verlaufstabelle zu verschieben.
quelle
Ich empfehle dringend, die gleiche Tabelle zu verwenden. Der Hauptgrund ist die Datenintegrität. Höchstwahrscheinlich wird es viele Tabellen mit Beziehungen geben, abhängig von den Benutzern. Wenn ein Benutzer gelöscht wird, möchten Sie diese Datensätze nicht verwaist lassen.
Verwaiste Aufzeichnungen zu haben, erschwert die Durchsetzung von Einschränkungen und erschwert das Nachschlagen historischer Informationen. Das andere zu berücksichtigende Verhalten, wenn ein Benutzer eine verwendete E-Mail bereitstellt, um alle alten Datensätze wiederherzustellen. Dies würde automatisch mit Soft Delete funktionieren. Was die Codierung betrifft, wird beispielsweise in meiner aktuellen c # linq-Anwendung die where deleted = 0-Klausel automatisch an das Ende aller Abfragen angehängt
quelle
Dies gibt mir einen schlechten Geruch von Design. Sie sollten eine solche Logik verbergen. Beispielsweise sollten Sie
UserService
eine MethodeisValidUser(userId)
für die Verwendung "auf Ihrem gesamten System" bereitstellen, anstatt wie folgt vorzugehen:Ihre Art, gelöschte Benutzer zu speichern, sollte sich nicht auf die Geschäftslogik auswirken.
Mit einer solchen Art der Verkapselung sollte das obige Argument den Ansatz Ihrer Persistenz nicht mehr beeinflussen. Dann können Sie sich mehr auf die Vor- und Nachteile der Persistenz konzentrieren.
Dinge zu beachten sind:
Normalerweise würde ich einen kombinierten Weg gehen:
quelle
Um diese Frage richtig zu beantworten, müssen Sie sich zunächst entscheiden: Was bedeutet "Löschen" im Kontext dieses Systems / dieser Anwendung?
Um diese Frage zu beantworten , müssen Sie noch eine weitere Frage beantworten: Warum werden Datensätze gelöscht?
Es gibt eine Reihe von guten Gründen, warum ein Benutzer Daten löschen muss. Normalerweise finde ich, dass es genau einen Grund (pro Tabelle) gibt, warum ein Löschen notwendig sein könnte. Einige Beispiele sind:
Es gibt auch einige sehr schlechte Gründe für ein hartes Löschen (dazu später mehr):
Warum, fragen Sie sich, ist das wirklich so eine große Sache? Was ist los mit guten alten
DELETE
?Soft Delete ist also besser, oder? Nein nicht wirklich:
Die Wahrheit ist, dass beide Ansätze falsch sind. Löschen ist falsch. Wenn Sie diese Frage tatsächlich stellen, bedeutet dies, dass Sie anstelle der Transaktionen den aktuellen Status modellieren. Dies ist eine schlechte, schlechte Praxis im Datenbankland.
Udi Dahan schrieb darüber in Don't Delete - Just Don't . Es gibt immer irgendeine Art von Aufgabe, Transaktion, Aktivität oder (mein bevorzugter Begriff) Ereignis, das tatsächlich das "Löschen" darstellt. Es ist in Ordnung, wenn Sie anschließend eine Denormalisierung in eine Tabelle mit dem aktuellen Status durchführen möchten, dies jedoch erst, nachdem Sie das Transaktionsmodell festgelegt haben.
In diesem Fall haben Sie "Benutzer". Benutzer sind im Wesentlichen Kunden. Kunden haben eine Geschäftsbeziehung mit Ihnen. Diese Beziehung verschwindet nicht einfach in Luft, weil sie ihren Account gekündigt hat. Was wirklich passiert ist:
In jedem Fall handelt es sich um denselben Kunden und möglicherweise um denselben Account (dh bei jeder Account-Verlängerung handelt es sich um einen neuen Servicevertrag). Warum löschen Sie Zeilen? Dies ist sehr einfach zu modellieren:
Das ist es. Das ist alles dazu. Sie müssen nie etwas löschen. Das oben Genannte ist ein recht gebräuchliches Design, das ein gutes Maß an Flexibilität bietet, das Sie jedoch ein wenig vereinfachen können. Sie könnten entscheiden, dass Sie die Stufe "Vereinbarung" nicht benötigen und "Konto" einfach zu einer "AccountStatus" -Tabelle wechseln lassen.
Wenn in Ihrer Anwendung häufig eine Liste der aktiven Vereinbarungen / Konten benötigt wird, ist dies eine (geringfügig) knifflige Abfrage, für die die folgenden Ansichten jedoch vorgesehen sind:
Und du bist fertig. Jetzt haben Sie etwas mit allen Vorteilen von Soft-Deletes, aber keinen der Nachteile:
Das einzige noch zu lösende Problem ist das Leistungsproblem. In vielen Fällen stellt sich heraus, dass es aufgrund des Clustered-Index kein Problem darstellt
AgreementStatus (AgreementId, EffectiveDate)
- dort wird nur sehr wenig nach E / A gesucht. Sollte es dennoch zu Problemen kommen, gibt es Möglichkeiten, diese zu lösen, indem Trigger, indizierte / materialisierte Ansichten, Ereignisse auf Anwendungsebene usw. verwendet werden.Sorgen Sie sich jedoch nicht zu früh um die Leistung - es ist wichtiger, das richtige Design zu finden. "Richtig" bedeutet in diesem Fall, die Datenbank so zu verwenden, wie sie als Transaktionssystem verwendet werden soll.
quelle
Ich arbeite derzeit mit einem System, in dem jede Tabelle ein gelöschtes Flag für Soft-Delete hat. Es ist der Fluch aller Existenz. Es bricht die relationale Integrität vollständig, wenn ein Benutzer einen Datensatz aus einer Tabelle "löschen" kann. Untergeordnete Datensätze, deren FK zurück zu dieser Tabelle liegt, werden jedoch nicht automatisch gelöscht. Sorgt nach Ablauf der Zeit für Mülldaten.
Daher empfehle ich separate Verlaufstabellen.
quelle
Den Tisch in zwei Teile zu teilen, wäre das Schlimmste, was man sich vorstellen kann.
Hier sind die zwei sehr einfachen Schritte, die ich empfehlen würde:
PS Entschuldigen Sie die monatelange Verzögerung bei der Beantwortung!
quelle
Wenn Sie gelöschte Konten wiederhergestellt hätten, wenn jemand mit derselben E-Mail-Adresse zurückgekehrt wäre, hätte ich alle Benutzer in derselben Tabelle belassen. Dies würde den Kontowiederherstellungsprozess trivial machen.
Wenn Sie jedoch neue Konten erstellen, ist es wahrscheinlich einfacher, gelöschte Konten in eine separate Tabelle zu verschieben. Das Live-System benötigt diese Informationen nicht, machen Sie sie also nicht zugänglich. Wie Sie sagen, werden die Abfragen bei größeren Datenmengen einfacher und möglicherweise auch schneller. Einfacherer Code ist auch einfacher zu pflegen.
quelle
Sie erwähnen das verwendete DBMS nicht. Wenn Sie über eine Oracle-Lizenz verfügen, können Sie die Benutzertabelle in zwei Partitionen unterteilen: aktive und gelöschte Benutzer.
quelle