Foundations for Professionals .NET Professionals im Profil guide to C# guidgen.de

Blog

Nutze den Augenblick
und teile der Welt mit, was Du zu sagen hast.

Primärschlüssel: GUID vs Identity

Mittwoch, 1. Juli 2009, 09:37 Uhr
Permalink | Kommentare (3) | Kommentare als RSSRSS

Am 13. Oktober 2008 haben Peter Bucher und ich unter dem Titel Noch Fragen, Bucher? Ja, Roden! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Juli 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Primärschlüssel: GUID vs Identity

So wohl Peter wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Peters Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

Die Aufgabe, eine Datenbankstruktur zu entwickeln, ist nicht leicht. Auf der einen Seite ist in der Regel eine möglichst hohe Normalisierung gewünscht, auf der anderen Seite darf die Performance nicht unter einer Vielzahl von Joins leiden.

Aus diesem Grund trifft man die fünfte Normalform – so wünschenswert ihre Umsetzung in der Theorie auch sein mag – in der Praxis nur ausgesprochen selten an: Der in der Datenbank notwendige Aufwand zur Bearbeitung einer Abfrage ist schlichtweg zu hoch.

In der Praxis trifft man daher zumeist auf Strukturen, die sich zwischen dritter, vierter und der sogenannten Boyce-Codd-Normalform bewegen. Essenziell ist in allen Fällen jedoch die Wahl eines geeigneten Primärschlüssels.

Ein Schlüssel ist dabei wie folgt definiert:

  • Ein Superschlüssel ist eine Menge von Feldern einer Tabelle, deren Zusammenspiel einen Datensatz eindeutig identifizieren. Beispielsweise könnte in vielen Fällen die Kombination aus Name, Vorname, Geburtsdatum und Adresse als Superschlüssel dienen, da es ausgesprochen unwahrscheinlich ist, dass zwei Personen gleichen Namens am gleichen Tag geboren sind und zudem noch an der gleichen Adresse wohnhaft sind.
  • Als Schlüsselkandidat bezeichnet man alle Superschlüssel, bei denen die Anzahl der verwendeten Felder minimal sind. Angenommen, beim vorigen Beispiel ließe sich das Geburtsdatum entfernen, ohne zugleich die Eindeutigkeit zu verlieren, dann wäre auch die Kombination aus Name, Vorname und Adresse ein Superschlüssel. Diese Version verwendet jedoch ein Feld weniger als die vorige. Sobald kein Feld mehr entfernt werden kann, ohne die Eindeutigkeit zu verlieren, spricht man von einem Schlüsselkandidaten.
  • Der Primärschlüssel ist schließlich ein (willkürlich) ausgewählter Schlüsselkandidat, der als Hauptidentifikationsmerkmal dient.

Eine interessante Frage ist, wie ein solcher Primärschlüssel aussehen sollte. Prinzipiell gibt es hierzu zwei Möglichkeiten: Entweder verwendet man lediglich Felder, die ohnehin als Bestandteil der Daten vorhanden sind – in diesem Fall nennt man den Schlüssel einen natürlichen Schlüssel, da alle enthaltenen Felder auch über eine natürliche Bedeutung in den Daten verfügen.

Oder man verwendet ein dediziertes, künstlich hinzugefügtes Feld, das zwar keine semantische Beziehung zu den Daten aufweist, dafür allerdings auf den Einsatz als Schlüssel optimiert wurde – in diesem Fall spricht man von einem Surrogatschlüssel.

Die Vorteile von Surrogatschlüsseln liegen auf der Hand: Da bei natürlichen Schlüsseln gegebenenfalls mehrere Felder zu einem Verbundschlüssel zusammengefasst werden müssen, ist die Arbeit mit ihnen arbeits- und zeitaufwändig. Surrogatschlüssel hingegen können auf das jeweilige Einsatzgebiet optimiert werden.

Die Frage lautet also: Wie sollte ein Surrogatschlüssel aussehen?

In der Praxis haben sich hierzu zwei Ansätze etabliert. Das erste Verfahren verwendet einen nummerischen Schlüssel, der im Regelfall durch die Datenbank hochgezählt und automatisch vergeben wird. Das zweite Verfahren nutzt sogenannte GUIDs – global eindeutige IDs.

Historisch bedingt sind nummerische Schlüssel wesentlich stärker verbreitet als GUIDs. Zudem verfügen GUIDs über einige immanente Nachteile:

  • Eine GUID belegt 16 Byte in der Datenbank, ein int hingegen nur 4 Byte. Abgesehen von dem zusätzlichen Speicherbedarf, der durch die Verwendung von GUIDs erzeugt wird, sind GUIDs aus diesem Grund auch nicht so performant wie int-Felder: Ein Vergleich auf 16 Bytes dauert logischerweise länger als ein Vergleich auf 4 Bytes.
  • Eine GUID ist schlechter lesbar als ein int. Das macht sich insbesondere beim Debuggen und bei der Fehlersuche bemerkbar.
  • Verschiedene GUIDs implizieren im Gegensatz zu fortlaufend vergebenen int-Werten keine Reihenfolge, sodass nicht nur eine natürliche Sortierung fehlt, sondern auch die Clusteringfähigkeit der Datenbank leidet.

Doch wo Schatten ist, ist auch Licht:

  • Eine GUID ist garantiert eindeutig – nicht nur in der Tabelle, sondern auch in Bezug auf die gesamte Datenbank und andere (!) Datenbanken. Das bedeutet, dass das Mergen von Datenbanken problemlos möglich ist, da es zu keinen Konflikten von Primärschlüsseln kommt, wie dies bei int-Werten häufig der Fall ist. Auch die Replikation von Datenbanken erfordert in der Regel die Verwendung von GUIDs – andernfalls wäre die Konsequenz ein äußerst aufwändiges Nachziehen von zu ändernden int-Werten.
  • Eine GUID kann vom Client erzeugt werden, der nächsthöhere int-Wert muss durch den Server erzeugt werden. Dies bedeutet im schlechtesten Fall, dass nach dem Einfügen eines Datensatzes ein weiterer Roundtrip zum Server nötig ist, um den erzeugten Schlüssel zu erhalten. Hierbei tritt bei der Verwendung von int-Werten häufig auch das Problem auf, wie mit nahezu zeitgleich eingefügten Datensätzen umgegangen wird – die Schlüssel müssen verbindungsbezogen zurückgegeben werden.

Ein besonderes Feature, das zwar nicht auf der Verwendung von GUIDs basiert, aber eindrucksvoll beweist, wie nützlich ein datenbankweit eindeutiger Schlüssel ist, enthält die Datenbank PostgreSQL: Die sogenannte OID (Object ID) ist ein automatisch von PostgreSQL vergebener eindeutiger Schlüssel, der in allen Datenbanken auf dem verwendeten Server eindeutig ist.

Die Besonderheit in PostgreSQL liegt nun darin, dass diese OID in Abfragen verwendet werden kann, um auf Datensätze zuzugreifen, ohne zu wissen, in welcher konkreten Datenbank oder Tabelle diese enthalten sind.

Aus all diesen Überlegungen kann als Fazit gezogen werden, dass die Verwendung von GUIDs generell empfohlen werden kann: Die genannten Vorteile überwiegen die wenigen Nachteile bei weitem, insbesondere auch im Hinblick auf die Zukunftssicherheit: Eine Datenbank, die ohnehin GUIDs verwendet, lässt sich ohne weiteres replizieren – eine Datenbank, die auf int-Werten basiert, nicht.

Als einzige Ausnahme dieser Regel sei der Fall genannt, wenn es auf das noch so kleinste Quentchen Performance ankommt: In diesem Fall sind int-Werte eventuell eine Option – allerdings stellt sich dann ohnehin die Frage, ob die Datenbank nicht per Scale-up oder Scale-out anders aufgebaut werden sollte.

Kommentare

Kommentar schreiben


(Zeigt dein Gravatar icon)  

  Country flag

biuquote
  • Kommentar
  • Live Vorschau
Loading