Derzeit verfügen wir über eine Datenbank und eine Anwendung, die voll funktionsfähig sind. Ich habe nicht die Möglichkeit, die Architektur zu diesem Zeitpunkt zu ändern. Heute hat jede Tabelle in der Datenbank ein Feld "IsDeleted" NOT NULL BIT mit dem Standardwert "0". Wenn die Anwendung Daten "löscht", aktualisiert sie einfach das IsDeleted-Flag auf 1.
Ich habe Probleme zu verstehen, wie die Indizes für jede der Tabellen strukturiert sein sollten. Im Moment implementiert jede Abfrage / Verknüpfung / etc immer die IsDeleted-Prüfung. Es ist ein Standard, dem unsere Entwickler folgen müssen. Davon abgesehen versuche ich festzustellen, ob alle meine gruppierten Primärschlüsselindizes für jede der Tabellen geändert werden müssen, um den Primärschlüssel UND das Feld IsDeleted BIT einzuschließen. Da JEDE Abfrage / Verknüpfung / etc. Muss die IsDeleted-Prüfung implementiert werden? Ist es eine angemessene Annahme, dass JEDER EINZELNE Index (auch nicht geclustert) das IsDeleted-Feld als erstes Feld des Index enthalten sollte?
Eine andere Frage, die ich habe, betrifft gefilterte Indizes. Ich verstehe, dass ich Filter auf die Indizes wie "WHERE IsDeleted = 0" setzen könnte, um die Größe der Indizes zu reduzieren. Würde dies jedoch die Verwendung des gefilterten Index verhindern, da jeder Join / jede Abfrage die IsDeleted-Prüfung implementieren muss (da die IsDeleted-Spalte in Join / Abfrage verwendet wird)?
Denken Sie daran, dass ich den IsDeleted-Ansatz nicht ändern kann.
quelle
IsDeleted
Spalte ist es unabhängig vom physischen Speicher wahrscheinlich sinnvoll, die Daten in zwei Ansichten (optional in verschiedenen Schemata) bereitzustellen, um sowohl das Parametrisierungsproblem zu lösen als auch Fehler beim Zugriff auf Daten zu machen, die nicht hätten sein dürfen weniger wahrscheinlich zugegriffen. Der Zugriff auf die Basisdaten ist nur in den seltenen Fällen relevant, in denen gelöschte und nicht gelöschte Daten kombiniert werden müssen und wenn die Zeilen tatsächlich auf "gelöscht" geschaltet werden müssen.Dies mag eine unpopuläre Meinung sein, aber ich glaube nicht, dass es ein "überall machen" gibt / eine einheitliche Antwort auf Ihre Frage.
Wenn Sie Abfragen haben, bei denen viele IsDeleted-Zeilen ohne Grund gescannt werden, besteht eine Lösung darin, einen gefilterten Nonclustered-Index zu erstellen, um diese Abfrage zu erfüllen.
Eine andere Möglichkeit besteht darin, eine indizierte Ansicht zu erstellen, die von einer Reihe verschiedener Abfragen genutzt werden kann und die nur nach den nicht gelöschten Zeilen gefiltert wird. Dies kann insbesondere in der Enterprise Edition hilfreich sein, in der der automatische Abgleich indizierter Ansichten ohne Angabe eines
NOEXPAND
Hinweises funktioniert .Bei kleinen oder stark gelesenen Tabellen kann das Hinzufügen von gefilterten Nonclustered-Indizes oder -Ansichten oder anderen Elementen zu unnötigem Overhead für Ihre Datenbank führen.
quelle
Unter der vernünftigen Annahme, dass Löschungen selten sind, sind keine Änderungen an den Indizes eine angemessene Lösung.
Ich fand, dass man früher oder später nach Verweisen auf gelöschte Zeilen fragen muss, und die Zeilen, die sich in den Indizes befinden, sind es plötzlich sehr wert.
Beachten Sie, dass Sie, sofern Sie keine Ansichten verwenden, alle Ihre Abfragen bearbeiten müssen, um die Filter trotzdem einzuschließen.
quelle
Ich habe ein System gesehen, in dem das IS_DELETED-Flag entweder 0 oder der Wert des PK ist. In anderen Systemen war es das Negativ der PK.
Da die meisten Abfragen Werte mit dem Schlüssel "natural" oder business (manchmal multi-field) abrufen, werden sie nur über Joins von PK abgefragt. Am Ende der Haupttabelle und aller verknüpften Tabellen wurde jedoch immer AND IS_DELETED = 0 hinzugefügt.
Dieses System verfügte auch über eine Prüftabelle für jede Transaktionstabelle, in der Änderungen nachverfolgt wurden. und die Anwendung hatte eine Funktion, um alle Datenänderungen einschließlich der gelöschten Daten anzuzeigen.
quelle
Ich hoffe, Sie haben Recht und die Möglichkeit, die Abfrage zu ändern.
Ich wollte einen wichtigen Punkt sagen, hoffe, ich kann es erklären.
In komplexen Abfragen werden sowohl where
Transaction table
als auchMaster
tables verwendet.Verwenden Sie
IsDeleted=0
nur inTransaction
Tabelle. Nicht in derMaster
Tabelle verwenden.Beispiel,
Es hat keinen Sinn
c.isdeleted=0
(in derCategory
Tabelle zu verwenden). Es ist unnötig.Gibt es in ähnlicher Weise einen Grund für die Verwendung
P.isdeleted=0
?Weil ich alle nicht gelöschten Bestellungen und deren Details haben möchte.
Wie kann
Product
gelöscht werden, wannOrder
istActive
oder woProductid
ist Referenz.Wenn Sie also in wichtigen Abfragen sorgfältig debuggen, können Sie möglicherweise einen Teil des Werts isdeleted = 0 entfernen.
Erstellen Sie nicht blindlings einen gefilterten Index, sondern wählen Sie zunächst alle sehr wichtigen und langsamen Abfragen aus.
Optimieren Sie diese langsamen Abfragen, und entscheiden Sie dann nur über den gefilterten Index oder die Optimierung des Index.
quelle