Frage

Ich habe mehrere Tabellen, deren einzige eindeutige Daten eine Uniqueidentifier-Spalte (eine Guid) sind.Da Guids nicht sequentiell sind (und clientseitig generiert werden, sodass ich newsequenzialid() nicht verwenden kann), habe ich für dieses ID-Feld einen nicht-primären, nicht gruppierten Index erstellt, anstatt den Tabellen einen gruppierten Primärindex zu geben Schlüssel.

Ich frage mich, welche Auswirkungen dieser Ansatz auf die Leistung hat.Ich habe gesehen, dass einige Leute vorgeschlagen haben, dass Tabellen einen automatisch inkrementierenden Ganzzahlwert („Identität“) als gruppierten Primärschlüssel haben sollten, auch wenn dieser keine Bedeutung hat, da dies bedeutet, dass die Datenbank-Engine selbst diesen Wert zu schnell verwenden kann Suchen Sie eine Zeile nach, anstatt ein Lesezeichen verwenden zu müssen.

Meine Datenbank wird über eine Reihe von Servern durch Zusammenführung repliziert, daher habe ich mich vor Identitäts-Int-Spalten gescheut, da es etwas schwierig ist, sie bei der Replikation richtig hinzubekommen.

Was sind deine Gedanken?Sollten Tabellen Primärschlüssel haben?Oder ist es in Ordnung, keine Clustered-Indizes zu haben, wenn es keine sinnvollen Spalten gibt, die auf diese Weise indiziert werden könnten?

War es hilfreich?

Lösung

Beim Umgang mit Indizes müssen Sie festlegen, wofür Ihre Tabelle verwendet werden soll.Wenn Sie hauptsächlich 1000 Zeilen pro Sekunde einfügen und keine Abfragen durchführen, beeinträchtigt ein Clustered-Index die Leistung.Wenn Sie 1000 Abfragen pro Sekunde durchführen, führt das Fehlen eines Index zu einer sehr schlechten Leistung.Wenn Sie Abfragen/Indizes optimieren möchten, verwenden Sie am besten den Abfrageplananalysator und den SQL Profiler in SQL Server.Dies zeigt Ihnen, wo Sie auf kostspielige Tabellenscans oder andere Leistungsblocker stoßen.

Was das Argument GUID vs. ID betrifft, finden Sie online Leute, die auf beides schwören.Mir wurde immer beigebracht, GUIDs zu verwenden, es sei denn, ich habe einen wirklich guten Grund, es nicht zu tun.Jeff hat einen guten Beitrag, der über die Gründe für die Verwendung von GUIDs spricht: https://blog.codinghorror.com/primary-keys-ids-versus-guids/.

Wie bei fast allem, was mit der Entwicklung zu tun hat, gibt es auch bei der Verbesserung der Leistung nicht die einzig richtige Antwort.Es hängt wirklich davon ab, was Sie erreichen möchten und wie Sie die Lösung implementieren.Die einzig wahre Antwort besteht darin, anhand von Leistungsmetriken zu testen, zu testen und noch einmal zu testen, um sicherzustellen, dass Sie Ihre Ziele erreichen.

Edit] @matt, nachdem ich weitere Nachforschungen über die GUID/ID -Debatte durchgeführt habe, habe ich diesen Beitrag gestoßen.Wie ich bereits erwähnt habe, gibt es keine wirklich richtige oder falsche Antwort.Dies hängt von Ihren spezifischen Implementierungsanforderungen ab.Aber das sind einige ziemlich triftige Gründe, GUIDs als Primärschlüssel zu verwenden:

Beispielsweise gibt es ein Problem, das als „Hotspot“ bekannt ist und bei dem bestimmte Datenseiten in einer Tabelle einem relativ hohen Währungskonflikt unterliegen.Grundsätzlich geschieht der Großteil des Datenverkehrs in einer Tabelle (und damit der Sperren auf Seitenebene) in einem kleinen Bereich der Tabelle gegen Ende.Neue Datensätze werden immer an diesen Hotspot gesendet, da IDENTITY ein fortlaufender Nummerngenerator ist.Diese Einfügungen sind problematisch, da sie eine exklusive Seitensperre auf der Seite erfordern, zu der sie hinzugefügt werden (dem Hotspot).Dadurch werden dank des Seitensperrmechanismus alle Einfügungen effektiv in einer Tabelle serialisiert.NewID() hingegen leidet nicht unter Hotspots.Mit der NewID()-Funktion generierte Werte sind nur bei kurzen Einfügungsstößen sequentiell (wobei die Funktion sehr schnell aufgerufen wird, z. B. während einer mehrzeiligen Einfügung), was dazu führt, dass die eingefügten Zeilen stattdessen zufällig über die Datenseiten der Tabelle verteilt werden von allen am Ende - so wird ein Hotspot durch Einfügungen vermieden.

Da die Einlagen zufällig verteilt sind, wird außerdem die Wahrscheinlichkeit von Seitenteilungen erheblich verringert.Auch wenn eine Seitenspaltung hier und da nicht so schlimm ist, summieren sich die Auswirkungen schnell.Bei IDENTITY ist der Seitenfüllfaktor als Optimierungsmechanismus ziemlich nutzlos und könnte genauso gut auf 100 % gesetzt werden – Zeilen werden auf keiner Seite außer der letzten eingefügt.Mit NewID() können Sie Fill Factor tatsächlich als leistungssteigerndes Tool nutzen.Sie können den Füllfaktor auf einen Wert festlegen, der dem geschätzten Volumenwachstum zwischen Indexneuerstellungen entspricht, und die Neuerstellungen dann mit dbcc reindex außerhalb der Spitzenzeiten planen.Dadurch werden die Leistungseinbußen durch Seitenaufteilungen effektiv bis zu Zeiten außerhalb der Spitzenzeiten verzögert.

Wenn Sie sogar denken Möglicherweise müssen Sie die Replikation für die betreffende Tabelle aktivieren. Dann können Sie den PK genauso gut zu einem eindeutigen Bezeichner machen und das GUID-Feld als ROWGUIDCOL kennzeichnen.Für die Replikation ist ein Guid-Feld mit eindeutigem Wert und diesem Attribut erforderlich. Falls keins vorhanden ist, wird eines hinzugefügt.Wenn ein geeignetes Feld vorhanden ist, wird einfach das vorhandene Feld verwendet.

Ein weiterer großer Vorteil der Verwendung von GUIDs für PKs ist die Tatsache, dass der Wert tatsächlich garantiert eindeutig ist – nicht nur unter allen von generierten Werten Das Server, sondern alle von generierten Werte alle Computern – sei es Ihr Datenbankserver, Webserver, App-Server oder Client-Rechner.Nahezu jede moderne Sprache verfügt mittlerweile über die Möglichkeit, eine gültige GUID zu generieren – in .NET können Sie System.Guid.NewGuid verwenden.Dies ist SEHR praktisch, insbesondere beim Umgang mit zwischengespeicherten Master-Detail-Datensätzen.Sie müssen keine verrückten temporären Schlüsselschemata verwenden, nur um Ihre Datensätze miteinander in Beziehung zu setzen, bevor sie festgeschrieben werden.Sie rufen einfach eine vollkommen gültige neue Guid vom Betriebssystem für den permanenten Schlüsselwert jedes neuen Datensatzes zum Zeitpunkt der Erstellung des Datensatzes ab.

http://forums.asp.net/t/264350.aspx

Andere Tipps

Der Primärschlüssel dient drei Zwecken:

  • gibt an, dass die Spalte(n) eindeutig sein sollen
  • gibt an, dass die Spalte(n) ungleich Null sein sollten
  • Dokumentieren Sie die Absicht, dass dies die eindeutige Kennung der Zeile ist

Die ersten beiden können auf viele Arten angegeben werden, wie Sie es bereits getan haben.

Der dritte Grund ist gut:

  • für Menschen, damit sie Ihre Absicht leicht erkennen können
  • für den Computer, sodass ein Programm, das Ihre Tabelle vergleichen oder anderweitig verarbeiten könnte, die Datenbank nach dem Primärschlüssel der Tabelle abfragen kann.

Ein Primärschlüssel muss kein automatisch inkrementierendes Zahlenfeld sein, daher würde ich sagen, dass es eine gute Idee ist, Ihre GUID-Spalte als Primärschlüssel anzugeben.

Ich bin einfach reingesprungen, weil Matt mich ein bisschen gelockt hat.

Sie müssen verstehen, dass, obwohl ein Clustered-Index standardmäßig auf den Primärschlüssel einer Tabelle gesetzt wird, die beiden Konzepte getrennt sind und separat betrachtet werden sollten.Ein CIX gibt die Art und Weise an, wie die Daten gespeichert und von NCIXs referenziert werden, während der PK eine Eindeutigkeit für jede Zeile bereitstellt, um die LOGISCHEN Anforderungen einer Tabelle zu erfüllen.

Eine Tabelle ohne CIX ist nur ein Heap.Eine Tabelle ohne PK wird oft als „keine Tabelle“ betrachtet.Am besten machen Sie sich separat mit den PK- und CIX-Konzepten vertraut, damit Sie beim Datenbankdesign sinnvolle Entscheidungen treffen können.

rauben

Niemand hat die eigentliche Frage beantwortet:Was sind die Vor- und Nachteile einer Tabelle ohne PK NOCH mit einem CLUSTERED-Index?Meiner Meinung nach, wenn Sie für schnellere Einfügungen optimieren (insbesondere inkrementelle Masseneinfügungen, z. B.wenn Sie Daten in großen Mengen in eine nicht leere Tabelle laden), eine solche Tabelle:mit KEINEM Clustered-Index, KEINEN Einschränkungen, KEINEN Fremdschlüsseln, KEINEN Standardwerten und KEINEM Primärschlüssel in einer Datenbank mit einfachem Wiederherstellungsmodell ist die beste Lösung.Wenn Sie diese Tabelle jemals abfragen möchten (anstatt sie vollständig zu scannen), möchten Sie möglicherweise nach Bedarf nicht gruppierte, nicht eindeutige Indizes hinzufügen, diese jedoch auf ein Minimum beschränken.

Auch ich habe immer gehört, dass ein automatisch inkrementierender Int für die Leistung gut ist, auch wenn Sie ihn nicht tatsächlich verwenden.

Ein Primärschlüssel muss kein automatisch inkrementierendes Feld sein. In vielen Fällen bedeutet dies nur, dass Sie Ihre Tabellenstruktur komplizieren.

Stattdessen sollte ein Primärschlüssel die minimale Sammlung von Attributen sein (beachten Sie, dass die meisten DBMS einen zusammengesetzten Primärschlüssel zulassen), die ein Tupel eindeutig identifiziert.

Technisch gesehen sollte es das Feld sein, von dem jedes andere Feld im Tupel funktionell vollständig abhängig ist.(Wenn dies nicht der Fall ist, müssen Sie möglicherweise normalisieren).

In der Praxis können Leistungsprobleme bedeuten, dass Sie Tabellen zusammenführen und ein inkrementelles Feld verwenden, aber ich erinnere mich an etwas darüber, dass vorzeitige Optimierung böse ist ...

Da Sie eine Replikation durchführen, sollten Sie sich von Ihren korrekten Identitäten fernhalten.Ich würde Ihre GUID zu einem Primärschlüssel machen, aber nicht gruppiert, da Sie newequentialid nicht verwenden können.Das scheint mir Ihr bester Kurs zu sein.Wenn Sie es nicht zu einem PK machen, sondern einen eindeutigen Index darauf setzen, kann das früher oder später dazu führen, dass die Leute, die das System warten, die FK-Beziehungen nicht richtig verstehen, was zu Fehlern führt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top