Tabelle im DB zum Generieren von Primärschlüsseln?

7

Verwenden Sie jemals eine separate Tabelle zum "Generieren" künstlicher Primärschlüssel für DB (und warum)? Was ich meine, ist eine Tabelle mit zwei Spalten, Tabellenname und aktueller ID - mit der Sie eine neue "ID" für eine Tabelle erhalten können, indem Sie einfach die Zeile mit diesem Tabellennamen sperren, den aktuellen Wert des Schlüssels abrufen, ihn erhöhen um eins und entsperren die Reihe. Warum bevorzugen Sie diese über die Standard-Integer-Identity-Spalte?

P.S. Die "Idee" stammt von Fowlers Patterns für Enterprise Application Architecture, übrigens ...

    
Denis Biondic 12.03.2010, 18:41
quelle

6 Antworten

10

Dies wird als Hi / Lo-Zuweisung bezeichnet.

Sie würden dies mit einem Trigger für INSERT auf Ihren Tabellen tun, der die ID aus dieser Tabelle abruft und sie vor oder nach dem Erhalt Ihrer ID inkrementiert, abhängig von Ihrer Wahl.

Dies wird häufig verwendet, wenn Sie mit mehreren Datenbank-Engines arbeiten müssen. Der autoincremental Bezeichner in Oracle ist durch eine SEQUENCE, die Sie mit SEQUENCE.NEXTVALUE aus einem BEFORE INSERT TRIGGER in Ihrer Datentabelle erhöhen.

Im Gegensatz dazu hat SQL Server IDENTITY-Spalten, die nativ automatisch inkrementieren, und dies wird vom DBE selbst verwaltet.

Damit Ihre Software auf beiden DBE funktioniert, müssen Sie zu einer Art Standard kommen, dann ist der häufigste "Standard", der dafür verwendet wird, die Hi / Lo-Zuweisung zum Primärschlüssel.

Dies ist ein Ansatz unter anderen. Heutzutage wird es mit ORM-Mapping-Tools wie NHibernate durch Konfiguration angeboten, so dass Sie weniger auf die Anwendungs- als auch auf die Datenbankseite achten müssen.

EDIT # 1

Da diese Art von Manöver nicht für einen globalen Gültigkeitsbereich verwendet werden kann, müsste eine solche Tabelle pro Datenbank oder Datenbankschema vorhanden sein. Auf diese Weise ist jedes Schema von dem anderen abhängig. Daten in einem Schema können jedoch nicht implizit mit demselben Schlüssel auf einen anderen verschoben werden, da dies möglicherweise mit einer bereits vorhandenen Zeile in Konflikt stehen würde.

Wie bei einem Sicherheitsschema greift es auf die gleiche Datenbank wie ein anderes Schema oder Benutzer zu, daher sollte keine zusätzliche Tabelle für ein bestimmtes Sicherheitsschema existieren.

    
Will Marcouiller 12.03.2010, 18:49
quelle
5

Wann immer Sie die Identitäts- oder GUID-Funktionen von SQL Server verwenden können, sollten Sie. Es gibt jedoch einige Situationen, in denen dies nicht möglich ist.

Ein Beispiel ist, dass der SQL-Server nur eine Identitätsspalte pro Tabelle zulässt. In seltenen Fällen wird eine Tabelle Datensätze enthalten, die sowohl eine private ID als auch eine öffentliche ID benötigen, und eine Grenze von einer Identitätsspalte bedeutet, dass das Generieren von beiden als Ganzzahlen ein Schmerz sein kann. Sie könnten immer eine GUID für eine verwenden, aber Sie wollen die Ganzzahl für die private ID für die Geschwindigkeit und Sie möchten vielleicht auch die öffentliche ID menschlicher lesbar als eine GUID sein.

In diesem Fall kann eine zusätzliche Tabelle zum Generieren der IDs sinnvoll sein. Allerdings würde ich es ein bisschen anders machen. Haben Sie noch zwei Spalten in der Tabelle, aber machen Sie eine "Schatten" - oder "Id-Mapping" -Tabelle für jede reale Tabelle. Eine der Spalten ist Ihre private ID (eindeutige Einschränkung) und eine wird Ihre öffentliche ID sein (Identität mit einem Inkrementwert von '7' oder '13' oder eine andere Zahl, die weniger offensichtlich ist als '1').

Der Hauptunterschied besteht darin, dass Sie das Sperren nicht selbst vornehmen möchten. Lassen Sie den SQL Server damit umgehen.

    
Joel Coehoorn 12.03.2010 18:49
quelle
3

Die einzige Zeit, die ich jemals benutzt habe, war, als ich eine Anwendung in BTrieve hatte und keine Identitätsspalte hatte. Und ich sollte auch sagen, als sie versuchten, diese Tabelle zu verwenden, verursachte sie eine massive Verlangsamung, als sie versuchten, Daten zu importieren, wegen all der zusätzlichen Lese- und Schreibvorgänge. Mein Freund hat es angeschaut und neu geschrieben, wie sie es getan haben, um es zu beschleunigen, aber die Moral der Geschichte ist, dass, wenn Sie etwas falsch machen, es brutale Konsequenzen geben kann.

Ich persönlich glaube nicht, dass ich das jemals tun möchte. Es gibt zu viele Fehlermöglichkeiten. Zwei Leute versuchen, den gleichen Schlüssel zu benutzen, weil sie vergessen haben, die Tabelle zu sperren, bevor sie die ID holen. Dies scheint nur etwas zu sein, das dem RDBMS möglichst überlassen bleiben sollte. Wie Will sagte, ist es leicht, diese Situation zu minimieren, aber wenn Sie nicht wissen, was Sie tun, kann es passieren.

    
kemiller2002 12.03.2010 18:46
quelle
2

Sie würden es überhaupt nicht bevorzugen.

Was auch immer Sie gewinnen, wenn Sie das Muster verwenden oder DB-agnostisch werden, Sie werden Kopfschmerzen, Unterstützung und Leistung verlieren.

    
gbn 12.03.2010 19:05
quelle
2
  

Sperren der Zeile mit diesem Tabellennamen,   den aktuellen Wert des Schlüssels erhalten,   inkrementieren Sie es um eins und entsperren Sie die   Zeile

Das klingt einfach, oder?

%Vor%

In Wirklichkeit ist es eine Katastrophe. In der Anwendung werden keine Aktivitäten als eigenständige Operation ausgeführt: Alle Vorgänge sind Teil von Transaktionen. Man kann die Zeile nicht einfach 'entsperren', weil das 'Entsperren' tatsächlich nur zur Commit-Zeit stattfindet. Das bedeutet, dass alle Transaktionen, die eine ID auf einer Tabelle benötigen, serialisiert sind und nur einer jederzeit fortfahren kann. Dies bedeutet auch, dass Transaktionen, die auf mehr als eine Tabelle zugreifen, wahrscheinlich beim Aktualisieren der Tabelle der IDs blockiert werden, da das Erzwingen der Update-Reihenfolge "Get the next Id" in der Praxis schwierig ist.

Um eine vollständige Serialisierung zu vermeiden, müssen die IDs in separaten, eigenständigen Transaktionen abgerufen werden, die sofort committen können (normalerweise eine implizite Auto-Commit-Transaktion auf dem UPDATE selbst). Dies erschwert jedoch die Anwendungslogik enorm. Jede Operation muss zwei separate Verbindungen zur Datenbank aufrechterhalten, eine für die normale Transaktionslogik und eine weitere für die benötigten IDs. Selbst dann kann das Update von IDs zu einem solchen Hotspot werden, dass es immer noch zu sichtbaren Konflikten und Blockierungen führen kann (ähnlich wie bei den gefürchteten 'Update-Seiten-Trefferzahlen +1', die in Web-Apps vorherrschen).

Kurz gesagt: Verwenden Sie IDENTITY. Die Identitätsgenerierung ist für hohe Parallelität optimiert.

    
Remus Rusanu 12.03.2010 19:19
quelle
1

Ich habe gesehen, dass dieses Muster verwendet wird, wenn Daten, die in einer Datenbank erstellt wurden, migriert, gesichert, gruppiert oder in einer anderen Datenbank bereitgestellt werden müssen. In dieser Situation möchten Sie zunächst sicherstellen, dass die Primärschlüssel nicht geändert werden müssen. Zweitens die Fremdschlüssel. Drittens extern exponierte Schlüssel oder dauerhafte Referenzen.

    
Jennifer Zouak 12.03.2010 19:04
quelle