Gründe für die Vermeidung großer ID-Werte

17

Wir arbeiten an einer Webanwendung, auf die Benutzer noch keinen Zugriff haben. Mein Chef bemerkte, dass neu erstellte Datensätze eine ID von über 10 000 erhalten, obwohl wir nur weniger als 100 Datensätze in der Tabelle haben. Sie ging davon aus, dass das Webinterface aus irgendeinem Grund mehr als 100-mal mehr temporäre Datensätze erstellt (und löscht), was dazu führen kann, dass wir innerhalb weniger Monate nach der Veröffentlichung nicht mehr in Reichweite sind.

Ich glaube nicht, dass sie bezüglich der Ursache der ID-Inflation Recht hat (die Kollegin, die darauf antworten kann, ist im Urlaub, wir wissen es also nicht genau), aber nehmen wir an, dass sie es ist. Sie sagte, sie würde es hassen, eine Bigint-Spalte zu verwenden, und sie möchte, dass wir die automatische Inkrementierung der ID-Spalte beenden und serverseitigen Code schreiben, der die erste "unbenutzte" Ganzzahl auswählt und sie als ID verwendet.

Ich bin ein Student der Informatik mit wenig praktischer Erfahrung und übernehme eine Junior-Entwickler-Rolle. Sie verfügt über jahrelange Erfahrung in der Verwaltung aller Datenbanken unserer Organisation und im Entwurf der meisten Datenbanken. Ich denke, dass sie in diesem Fall falsch ist, dass eine Bigint-ID nichts zu befürchten ist und dass die Nachahmung der DBMS-Funktionalität nach einem Antipattern riecht. Aber ich traue meinem Urteil noch nicht.

Was sind die Argumente für und gegen jede Position? Welche schlechten Dinge können passieren, wenn wir einen Bigint verwenden, und welche Gefahren birgt die Neuerfindung der Funktion zum automatischen Inkrementieren des Rads ? Gibt es eine dritte Lösung, die besser ist als beide? Was könnte ihre Gründe dafür sein, eine Inflation von ID-Nennwerten vermeiden zu wollen? Ich bin auch daran interessiert, über pragmatische Gründe zu hören - vielleicht funktionieren Bigint-IDs theoretisch, verursachen aber in der Praxis Kopfschmerzen?

Es wird nicht erwartet, dass die Anwendung sehr große Datenmengen verarbeitet. Ich bezweifle, dass es in den nächsten Jahren 10 000 tatsächliche Rekorde erreichen wird.

Wenn es einen Unterschied macht, verwenden wir Microsoft SQL Server. Die Anwendung ist in C # geschrieben und verwendet Linq to SQL.

Aktualisieren

Vielen Dank, ich fand die vorhandenen Antworten und Kommentare interessant. Aber ich fürchte, Sie haben meine Frage falsch verstanden, und sie enthalten das, was ich wissen wollte.

Ich bin nicht wirklich besorgt über den wahren Grund für die hohen IDs. Wenn wir es nicht alleine finden können, könnte ich eine andere Frage stellen. Was mich interessiert, ist, den Entscheidungsprozess in diesem Fall zu verstehen. Nehmen Sie dazu bitte an, dass die Anwendung 1000 Datensätze pro Tag schreibt und 9999 davon löscht . Ich bin mir fast sicher, dass dies nicht der Fall ist, aber das hat meine Chefin geglaubt, als sie ihre Anfrage gestellt hat. Was wäre also unter diesen hypothetischen Umständen das Für und Wider, entweder Bigint zu verwenden oder unseren eigenen Code zu schreiben, der IDs zuweist (auf eine Weise, die die IDs bereits gelöschter Datensätze wiederverwendet, um sicherzustellen, dass es keine Lücken gibt)?

Was den eigentlichen Grund betrifft, vermute ich stark, dass dies daran liegt, dass wir einmal Code geschrieben haben, um Daten aus einer anderen Datenbank zu importieren, um zu beweisen, dass eine spätere Migration bis zu einem gewissen Grad durchgeführt werden kann. Ich glaube, mein Kollege hat während des Imports tatsächlich mehrere tausend Datensätze erstellt und später gelöscht. Ich muss bestätigen, ob dies tatsächlich der Fall war, aber wenn ja, besteht nicht einmal Handlungsbedarf.

rumtscho
quelle
Siehe SM Ahasan Habibs Beitrag unter codeproject.com/Tips/668042/…
RLF
Könntest Du das erläutern? Erhalten neue IDs einfach Werte> 10000? Oder haben neue IDs Lücken von 10000? Und wie viele IDs werden voraussichtlich für das zukünftige App-Leben benötigt?
user2338816
1
Bezüglich der Suche nach der ersten nicht verwendeten ID gibt es in Bill Karwins Buch "SQL Antipatterns" ein Kapitel darüber. Also ja, es kann durchaus als Antimuster angesehen werden!
Thomas Padron-McCarthy

Antworten:

24

Ohne den Code zu sehen, ist es ziemlich schwer abschließend zu sagen, was passiert. Wahrscheinlich wird der IDENTITYWert jedoch zwischengespeichert, was nach dem Neustart von SQL Server zu Lücken im Wert führt. Unter /programming/17587094/identity-column-value-suddenly-jumps-to-1001-in-sql-server finden Sie einige gute Antworten und Informationen dazu.

Ein einfaches INTFeld kann Werte bis zu 2.147.483.647 enthalten. Sie können den Identitätswert tatsächlich bei -2.147.483.648 beginnen und dabei 32 Bit mit Werten angeben. 4 Milliarden verschiedene Werte. Ich bezweifle sehr, dass Ihnen die Werte ausgehen, die Sie verwenden können. Angenommen , Ihre Anwendung wird 1000 Werte für jede tatsächliche Zeilenraubend hinzugefügt, dann würden Sie brauchen fast 12.000 Zeilen pro Tag zu erschaffen täglich von IDs laufen in 6 Monaten vorausgesetzt , Sie den gestartet IDENTITYWert bei 0, und ein INT verwendet hat . Wenn Sie einen BIGINT verwenden, müssen Sie 21 Millionen Jahrhunderte warten, bis Ihnen die Werte ausgehen, wenn Sie 12.000 Zeilen pro Tag schreiben und 1.000 "Werte" pro Zeile verbrauchen.

Abgesehen davon, wenn Sie BIGINTals Datentyp für das Identitätsfeld verwenden möchten, ist daran sicherlich nichts auszusetzen. Das gibt Ihnen in jeder Hinsicht ein unbegrenztes Angebot an Werten, die Sie nutzen können. Der Leistungsunterschied zwischen einem INT und einem BIGINT ist auf moderner 64-Bit-Hardware praktisch nicht vorhanden und wird beispielsweise bei der Erstellung von NEWID()GUIDs vorgezogen.

Wenn Sie Ihre eigenen Werte für die ID-Spalte verwalten möchten, können Sie eine Schlüsseltabelle erstellen und dies auf ziemlich sichere Weise tun, indem Sie eine der in den Antworten zu dieser Frage aufgeführten Methoden verwenden: Gleichzeitigen Zugriff auf eine Schlüsseltabelle ohne Deadlocks in SQL Server

Wenn Sie SQL Server 2012+ verwenden, können Sie auch ein SEQUENCEObjekt verwenden, um ID-Werte für die Spalte abzurufen . Sie müssen die Sequenz jedoch so konfigurieren, dass keine Werte zwischengespeichert werden. Beispielsweise:

CREATE SEQUENCE dbo.MySequence AS INT START WITH -2147483648 INCREMENT BY 1 NO CACHE;

Als Antwort auf die negative Wahrnehmung Ihres Chefs von "hohen" Zahlen würde ich sagen, welchen Unterschied macht es? Vorausgesetzt , dass Sie ein verwenden INTFeld, mit ein IDENTITY, könnte man in der Tat beginnt die IDENTITYan 2147483647und „Erhöhung“ der Wert durch -1. Dies würde absolut keinen Unterschied hinsichtlich des Speicherverbrauchs, der Leistung oder des verwendeten Speicherplatzes machen, da eine 32-Bit-Zahl 4 Bytes beträgt, unabhängig davon, ob dies der Fall ist 0oder nicht 2147483647. 0In binär ist, 00000000000000000000000000000000wenn in einem 32-Bit- INTFeld mit Vorzeichen gespeichert . 2147483647ist01111111111111111111111111111111- Beide Nummern belegen sowohl im Arbeitsspeicher als auch auf der Festplatte genau den gleichen Speicherplatz und erfordern für die Verarbeitung genau die gleiche Anzahl von CPU-Vorgängen. Es ist weitaus wichtiger, Ihren Anwendungscode korrekt zu gestalten, als sich über die in einem Schlüsselfeld gespeicherte tatsächliche Nummer Gedanken zu machen.

Sie haben nach den Vor- und Nachteilen gefragt, entweder (a) eine ID-Spalte mit größerer Kapazität wie a zu verwenden BIGINToder (b) eine eigene Lösung zu entwickeln, um ID-Lücken zu vermeiden. Um diese Bedenken zu beantworten:

  1. BIGINTstatt INTals Datentyp für die betreffende Spalte. Die Verwendung von a BIGINTerfordert die doppelte Menge an Speicher sowohl auf der Festplatte als auch im Arbeitsspeicher für die Spalte selbst. Wenn die Spalte der Primärschlüsselindex für die betreffende Tabelle ist, speichert jeder nicht gruppierte Index, der an die Tabelle angehängt ist, den BIGINTWert ebenfalls mit der doppelten Größe eines INT, ebenfalls sowohl im Arbeitsspeicher als auch auf der Festplatte. SQL Server speichert Daten auf der Festplatte in 8-KB-Seiten, wobei die Anzahl der "Zeilen" pro "Seite" von der "Breite" jeder Zeile abhängt. Wenn Sie beispielsweise eine Tabelle mit 10 Spalten haben, von denen jede eine ist INT, können Sie ungefähr 160 Zeilen pro Seite speichern. Wenn diese Spalten stattdessen warenBIGINTIn Spalten können Sie nur 80 Zeilen pro Seite speichern. Bei einer Tabelle mit einer sehr großen Anzahl von Zeilen bedeutet dies eindeutig, dass die zum Lesen und Schreiben der Tabelle erforderlichen E / A-Vorgänge in diesem Beispiel für eine bestimmte Anzahl von Zeilen doppelt so hoch sind. Zugegeben, dies ist ein ziemlich extremes Beispiel - wenn Sie eine Zeile bestehend aus einer einzelnen INToder BIGINTSpalte und einer einzelnen NCHAR(4000)Spalte hätten, würden Sie (vereinfacht) eine einzelne Zeile pro Seite erhalten, unabhängig davon, ob Sie eine INToder eine verwendet haben BIGINT. In diesem Szenario würde es keinen nennenswerten Unterschied machen.

  2. Rollen Sie Ihr eigenes Szenario, um Lücken in der ID-Spalte zu vermeiden. Sie müssen Ihren Code so schreiben, dass die Bestimmung des "nächsten" zu verwendenden ID-Werts nicht mit anderen Aktionen in Konflikt steht, die mit der Tabelle durchgeführt werden. Etwas in der Art von SELECT TOP(1) [ID] FROM [schema].[table]Naivität fällt mir ein. Was ist, wenn mehrere Akteure gleichzeitig versuchen, neue Zeilen in die Tabelle zu schreiben? Zwei Akteure könnten leicht den gleichen Wert erhalten, was zu einem Schreibkonflikt führen würde. Um dieses Problem zu umgehen, muss der Zugriff auf die Tabelle serialisiert werden, wodurch die Leistung verringert wird. Es wurden viele Artikel über dieses Problem geschrieben. Ich überlasse es dem Leser, nach diesem Thema zu suchen.

Die Schlussfolgerung hier ist: Sie müssen Ihre Anforderungen verstehen und sowohl die Anzahl der Zeilen als auch die Zeilenbreite sowie die Anforderungen an die Parallelität Ihrer Anwendung richtig einschätzen. Wie gewohnt ist It Depends ™.

Max Vernon
quelle
4
+1, aber ich würde den Platzbedarf von BIGINT nicht verwerfen. Nicht so sehr für den Speicherplatz auf der Festplatte, sondern für die E / A und den verschwendeten Speicherplatz. Sie können einen Großteil davon mithilfe der Datenkomprimierung ausgleichen, sodass Sie die Hauptlast des BIGINT-Typs erst dann spüren, wenn Sie 2 Milliarden überschreiten. Idealerweise würden sie das Problem einfach beheben (ich zögere, es als Fehler zu bezeichnen) - während sich die Leute nicht um Lücken kümmern sollten und die Leute ihre Server nicht 15 Mal am Tag neu starten sollten, haben wir beide Szenarien ziemlich weit verbreitet und oft im Tandem.
Aaron Bertrand
3
Sehr gute Punkte, Aaron, wie immer. Ich würde sowieso eher eine INT verwenden, da BIGINT so ziemlich totaler Overkill ist, es sei denn, sie erwarten eine große Anzahl von Zeilen.
Max Vernon
Ein BIGINT-Datentyp für eine ID-Spalte hat nur dann große Auswirkungen auf den Arbeitsspeicher, wenn Sie Hunderttausende oder mehr davon gleichzeitig im Arbeitsspeicher haben. Selbst dann ist es wahrscheinlich ein kleiner Bruchteil der gesamten Zeilengröße.
user2338816
2
@ user2338816 das ist der Punkt - wenn die Tabelle groß wird, gibt es viele im Speicher. Da es sich bei der Identitätsspalte in der Regel um den Clustering-Schlüssel handelt, sind dies auch zusätzliche 4 Byte für jede einzelne Zeile in jedem Index. Wird es in jedem Einzelfall eine Rolle spielen? Soll es ignoriert werden? Absolut nicht. Niemand scheint etwas über die Skalierbarkeit zu sagen, bis es zu spät ist.
Aaron Bertrand
3
Wenn Sie jedoch eine berechtigte Erwartung haben, die Sie möglicherweise benötigen, werden bigintSie sich wahrscheinlich dafür bedanken, dass Sie dies im Voraus entschieden haben, anstatt dies einer Tabelle mit Milliarden von Zeilen hinzufügen zu müssen.
Martin Smith
6

Die Hauptaufgabe besteht darin, die Ursache zu finden, warum der aktuelle Wert so hoch ist.

Die vernünftigste Erklärung für SQL Server-Versionen vor SQL2012 - vorausgesetzt, Sie sprechen von einer Testdatenbank - wäre, dass ein Auslastungstest gefolgt von einer Bereinigung durchgeführt wurde.

Ab SQL2012 liegt der wahrscheinlichste Grund in mehreren Neustarts der SQL-Engine (wie im ersten angegebenen Link Max erläutert).

Wenn die Lücke durch ein Testszenario verursacht wird, besteht aus meiner Sicht kein Grund zur Sorge. Aber um auf der sicheren Seite zu sein, würde ich die Identitätswerte während der normalen Verwendung der Anwendung sowie vor und nach einem Motorneustart überprüfen.

Es ist "lustig", dass MS angibt, dass beide Alternativen (entweder Ablaufverfolgungsflag 272 oder das neue SEQUENCE-Objekt) die Leistung beeinträchtigen könnten.

Es könnte die beste Lösung sein, BIGINT anstelle von INT zu verwenden, nur um auf der sicheren Seite zu sein, um die nächsten "Verbesserungen" von MS abzudecken ...

Lmu92
quelle
Ich habe meine Frage wahrscheinlich falsch formuliert, aber ich bin nicht wirklich daran interessiert, die Ursache zu finden. Es besteht eine hohe Wahrscheinlichkeit, dass es sich entweder um etwas handelt, das nicht mehr angezeigt wird (Ergebnisse eines Testlaufs), oder um eine falsche Entwurfsentscheidung in der Anwendung, die außerhalb der Datenbank gelöst werden kann. Es ging darum zu verstehen, warum ein erfahrener DBA hohe IDs als schlecht oder schlechter ansieht als unser eigenes ID-Management.
Rumtscho
2

Rumtscho, wenn Sie nur 1000 Zeilen pro Tag erstellen, gibt es wenig zu entscheiden - verwenden Sie den Datentyp INT mit einem Identitätsfeld und machen Sie es fertig. Eine einfache Rechnung besagt, dass Sie, wenn Sie Ihrer App einen 30-jährigen Lebenszyklus geben (unwahrscheinlich), 200.000 Zeilen pro Tag haben könnten und immer noch im positiven Zahlenbereich eines INT-Datentyps liegen.

Die Verwendung von BigInt ist in Ihrem Fall ein Overkill. Es kann auch Probleme verursachen, wenn auf Ihre App oder Daten über ODBC zugegriffen wird (z. B. in Excel oder MS Access usw.). Bigint übersetzt die meisten ODBC-Treiber nicht gut in Desktop-Apps.

Was GUIDS betrifft, gibt es neben dem zusätzlichen Speicherplatz und den zusätzlichen E / A das große Problem, dass sie von Natur aus nicht sequenziell sind. Wenn sie also Teil eines sortierten Index sind, können Sie davon ausgehen, dass jede Einfügung ausgeführt wird erfordern, dass der Index neu sortiert wird. - Jim

jimo3
quelle
Guter Punkt zu GUIDs, es sei denn, Sie verwenden NEWSEQUENTIALID (). Ich stimme weiterhin zu, es gibt keinen guten Grund, sie in dieser Frage zu verwenden.
Max Vernon
1

Gibt es eine Lücke zwischen den verwendeten Werten? Oder die Startwerte sind 10.000 und von da an addieren sich alle 1? Manchmal, wenn die Nummer an Kunden vergeben wird, ist die anfängliche Nummer größer als Null, beispielsweise 1500, sodass der Kunde nicht erkennt, dass das System "neu" ist.

Der Nachteil der Verwendung von bigint anstelle von smallint besteht darin, dass bigint "mehr Speicherplatz" verwendet, wenn beim Lesen von Datenträgern weniger Datenträgerblöcke für jeden Datenträger gelesen werden. Wenn Ihr Zeilenabstand klein ist, kann dies ein Nachteil sein, wenn nicht, spielt es keine Rolle. Es spielt auch keine Rolle, wenn Sie nicht viele Ressourcen gleichzeitig abfragen und über die richtigen Indizes verfügen.

Und wie bereits in einer anderen Antwort erwähnt, sollten Sie sich keine Sorgen machen, wenn Sie befürchten, dass Ihnen die Indizes ausgehen, wenn Sie nicht über ein Millionärsgeschäft verfügen. Das Erfinden eines Mechanismus zum "Wiederherstellen von IDs" ist teuer und fügt der Software Fehlerpunkte und Komplexität hinzu.

Grüße

ctutte
quelle
2
Das OP sieht Lücken beim Neustart des Dienstes. Dies liegt an diesem Problem . Ich denke auch nicht, dass ein Smallint kurzfristig ein guter Kompromiss für die Arbeit ist, die nötig ist, um ihn später zu beheben.
Aaron Bertrand
@ AaronBertrand Ich fürchte, andere haben das falsch verstanden, als sie diese Möglichkeit vorschlugen. Ich bin mir ziemlich sicher, dass dies nicht die Ursache für die hohen Zahlen ist, aber selbst wenn es so wäre, habe ich nicht versucht, die Ursache zu finden, sondern herauszufinden, welche Argumente für und gegen die vorgeschlagenen Lösungen sprechen können. Einzelheiten finden Sie in meinem Update.
Rumtscho
@rumtscho eigentlich hebt diese Antwort einen guten Punkt hervor, auch wenn sie Ihre Frage nicht direkt anspricht: "Das Erfinden eines Mechanismus zum 'Wiederherstellen von IDs' ist teuer und fügt der Software Fehlerpunkte und Komplexität hinzu."
Doktor J
@DoktorJ Ich stimme dir zu. Ich war derjenige, der die Antwort positiv bewertet hat :) Ich wollte nur das Missverständnis beseitigen, deshalb habe ich meinen ersten Kommentar hinterlassen.
Rumtscho
1

Wenn ich Ihr Chef wäre , würden mich die Gründe für die unerwartet hohen ID-Werte am meisten interessieren ... wie ich es sehe, für jedes der beiden von Ihnen beschriebenen Szenarien:

  1. WENN die vorherigen Tests Identitätswerte erhöht haben, würde mich Ihr anderer Kommentar zur erwarteten Anzahl von Datensätzen auch dazu bewegen, einen kleineren Schlüsseltyp vorzuschlagen. Ehrlich gesagt würde ich auch überlegen, ob es möglich ist, die Sequenz zurückzusetzen und vorhandene Datensätze neu zu nummerieren, wenn der Test für die aktuell vorgesehene Verwendung der Tabelle nicht geeignet ist (die meisten würden diesen Overkill in Betracht ziehen - "es hängt davon ab").

  2. WENN die Mehrheit der in die Tabelle geschriebenen Datensätze gelöscht wird, sobald ich beabsichtige, stattdessen zwei Tabellen zu verwenden. eine temporäre Tabelle, in der Aufzeichnungen nicht langfristig aufbewahrt werden, und eine andere, in der nur Aufzeichnungen dauerhaft aufbewahrt werden, die wir erstellen. Ihre Erwartungen bezüglich der Anzahl der Langzeitdatensätze legen mir die Verwendung eines kleineren Typs für Ihre Schlüsselspalte nahe, und einige Datensätze pro Tag führen kaum dazu, dass Sie aufgrund von Leistungsproblemen einen Datensatz von einer Tabelle in eine andere verschieben müssen einer. Ich vermute, dass es nicht Ihr Szenario ist, aber stellen Sie sich vor, dass eine Einkaufswebsite möglicherweise lieber einen Warenkorb / BasketItem verwaltet, und wenn eine Bestellung tatsächlich aufgegeben wird, werden die Daten in den Bestell- / BestellItem-Satz verschoben.

Zusammenfassen; Meiner Meinung nach sind BIGINTs nicht unbedingt zu befürchten, aber für viele Szenarien unnötig groß. Wenn die Tabelle nie groß wird, werden Sie nie bemerken, dass Ihre Auswahl an Datentypen übertrieben war ... aber wenn Sie Tabellen mit Millionen von Zeilen und vielen FK-Spalten haben, die GROSS sind, obwohl sie kleiner hätten sein können - dann möchten Sie vielleicht die Die Typen wurden konservativer ausgewählt (berücksichtigen Sie nicht nur die Schlüsselspalten, sondern auch alle vorderen Schlüsselspalten und alle von Ihnen aufbewahrten Sicherungen usw.). Speicherplatz ist nicht immer günstig (betrachten Sie SAN-Speicher an verwalteten Speicherorten - dh der Speicherplatz wird angemietet).

Im Wesentlichen plädiere ich dafür, Ihre Auswahl des Datentyps immer und nicht manchmal sorgfältig zu überlegen . Sie werden Verwendungsmuster nicht immer richtig vorhersagen, aber ich denke, Sie werden in der Regel bessere Entscheidungen treffen, als immer davon auszugehen, dass "größer ist besser". Im Allgemeinen wähle ich den kleinsten Typ aus, der den erforderlichen und vernünftigen Wertebereich enthalten kann, und ich werde INT, SMALLINT und sogar TINYINT gerne in Betracht ziehen, wenn ich der Meinung bin, dass der Wert in absehbarer Zukunft wahrscheinlich in diesen Typ passt. Es ist jedoch unwahrscheinlich, dass die kleineren Typen mit IDENTITY-Spalten verwendet werden, sie können jedoch problemlos mit Nachschlagetabellen verwendet werden, in denen Schlüsselwerte manuell festgelegt werden.

Schließlich können die von Menschen verwendeten Technologien ihre Erwartungen und Antworten erheblich beeinflussen. Einige Tools verursachen mit größerer Wahrscheinlichkeit Lücken in den Bereichen, z. B. indem Identitätsbereiche pro Prozess vorab gebucht werden. Im Gegensatz dazu schlägt @DocSalvager eine gründliche, überprüfbare Sequenz vor, die den Standpunkt Ihres Chefs widerspiegelt. Ich persönlich habe nie so viel Autorität gefordert - obwohl die allgemeine Regel, dass Identitäten sequentiell und im Allgemeinen lückenlos sind, mir in Support-Situationen und bei der Problemanalyse oft unglaublich nützlich war.

Nij
quelle
1

Was wären die Vor- und Nachteile, wenn Sie entweder bigint verwenden oder unseren eigenen Code schreiben, der IDs zuweist (wobei die IDs bereits gelöschter Datensätze wiederverwendet werden, um sicherzustellen, dass keine Lücken entstehen)?

Die Verwendung bigintals Identität und das Leben mit den Lücken:

  • Es ist alles eingebaute Funktionalität
  • Sie können sicher sein, dass es sofort funktioniert
  • Es wird Speicherplatz verschwendet, da Sie intimmer noch etwa 2 Millionen Tage Daten erhalten. Weitere Seiten müssen gelesen und geschrieben werden. Indizes können tiefer werden. (Bei diesen Mengen ist dies jedoch kein wesentliches Problem).
  • Eine Ersatzschlüsselspalte soll bedeutungslos sein, daher sind Lücken in Ordnung. Wenn es den Benutzern angezeigt wird und Lücken als signifikant interpretiert werden, machen Sie es falsch.

Roll deinen eigenen:

  • Ihr Entwicklerteam wird die gesamte Entwicklungs- und Fehlerbehebungsarbeit für immer erledigen.
  • willst du nur lücken am schwanz oder auch in der mitte füllen Gestaltungsentscheidungen zum Streiten.
  • Jeder Schreibvorgang muss starke Sperren auslösen, um zu verhindern, dass gleichzeitige Prozesse dieselbe neue ID erhalten, oder um Konflikte post facto zu lösen .
  • Im schlimmsten Fall müssen Sie jede Zeile in der Tabelle aktualisieren, um die Lücken zu schließen, wenn rowid = 1 gelöscht wird. Dies wird Nebenläufigkeit und Leistung beeinträchtigen, was mit all den kaskadierenden Fremdschlüsselaktualisierungen usw. zusammenhängt.
  • faul oder eifrig lückenfüllend? Was passiert mit der Parallelität, während dies geschieht?
  • Sie müssen für die neue ID lesen, bevor Sie schreiben = zusätzliche Last.
  • Für eine effiziente Lückenfindung wird ein Index für die ID-Spalte benötigt.
Michael Green
quelle
0

Wenn Sie wirklich besorgt sind, den oberen Schwellenwert von INT für Ihre PKs zu erreichen, sollten Sie die Verwendung von GUIDs in Betracht ziehen. Ja, ich weiß, dass es 16 Bytes vs 4 Bytes sind, aber die Festplatte ist billig.

Hier ist eine gute Zusammenfassung der Vor- und Nachteile.

Tim Goyer
quelle
4
+1, weil dies eine Lösung ist, aber siehe Aarons Kommentar zu Max 'Antwort aus einem Grund, warum "Festplatte ist billig" kein Grund ist, GUIDs zu verwenden, ohne die Optionen sorgfältig abzuwägen.
Jack Douglas
1
Hier ist eine bessere Beschreibung von einem SQL Server-Experten für Index und Architektur als von einem Entwickler: sqlskills.com/blogs/kimberly/disk-space-is-cheap
Aaron Bertrand
Oh, und natürlich Vorsicht vor den Seitenteilen von NEWID ()
Max Vernon
1
Mein Chef scheint hohe Werte nur zu beanstanden, weil sie hoch aussehen. Ich hoffe, dass diese Frage mir mehr mögliche Einwände aufzeigt, aber wenn dies eines ihrer Hauptargumente ist, würde sie wahrscheinlich noch negativer auf GUIDs reagieren.
Rumtscho
1
@rumtscho Sagen Sie Ihrem Chef, dass eine Ersatzzahl nur eine bedeutungslose Zahl ist ("Größe" der Zahl ist irrelevant) und dass Lücken in einer Sequenz natürlich und weitgehend unvermeidbar sind.
Aaron Bertrand
0

RDBMS-Primärschlüssel (normalerweise als 'ID' bezeichnete Spalte)
In RDBMS-Spalten (Feldern), die automatisch inkrementiert werden, können Lücken nicht vermieden werden. Sie sind in erster Linie dazu gedacht, eindeutige PKs zu erstellen. Aus Gründen der Leistung ordnen die Hauptprodukte diese in Chargen zu, sodass automatische Wiederherstellungsmechanismen für verschiedene normale Betriebsstörungen dazu führen können, dass Zahlen nicht verwendet werden. Das ist normal.

Nicht
unterbrochene Sequenzen Wenn Sie eine nicht unterbrochene Sequenznummer benötigen, wie dies häufig von Benutzern erwartet wird, sollte es sich um eine separate Spalte handeln, die programmgesteuert zugewiesen wird und nicht die PK sein darf . Somit können diese 1000 Datensätze alle dieselbe Nummer in dieser Spalte haben.

Warum wollen Benutzer ununterbrochene Sequenzen?
Fehlende Sequenznummern sind das grundlegendste Fehlerzeichen, das bei jeder Art von Prüfung aufgedeckt wird. Dieses "Bookkeeping-101" -Prinzip ist allgegenwärtig. Was jedoch für eine kleine Anzahl von Datensätzen funktioniert, die von Hand gepflegt werden, hat ein ernstes Problem, wenn es auf eine sehr große Anzahl von Datensätzen in Datenbanken angewendet wird.

Die Wiederverwendung von Schlüsselwerten für nicht verwandte Datensätze macht die Datenbank ungültig. Die
Verwendung der ersten nicht verwendeten Ganzzahl führt die Wahrscheinlichkeit ein, dass eine Zahl zu einem späteren Zeitpunkt für Datensätze wiederverwendet wird, die nicht mit dem Original zusammenhängen. Das macht die Datenbank als genaue Darstellung der Tatsachen unzuverlässig. Dies ist der Hauptgrund dafür, dass Autoinkrementierungsmechanismen absichtlich so konzipiert sind, dass sie einen Wert niemals wiederverwenden.

DocSalvager
quelle