Über die Verwendung von PostgreSQL und UUIDs als Primärschlüssel
(maciejwalkowiak.com)- UUIDs werden häufig als Primärschlüssel in Datenbanktabellen verwendet
- Sie lassen sich leicht erzeugen, einfach zwischen verteilten Systemen teilen und garantieren Eindeutigkeit
- Angesichts der Größe von UUIDs fragt man sich zwar, ob das die richtige Wahl ist, aber oft kann man das nicht selbst entscheiden
- Dieser Artikel konzentriert sich nicht auf die Frage „Sind UUIDs ein geeignetes Format für Schlüssel?“, sondern erklärt, wie man UUIDs in PostgreSQL effizient als Primärschlüssel verwendet
PostgreSQL und UUIDs als Primärschlüssel verwenden
- Was ist eine UUID?
- UUIDs werden häufig als Primärschlüssel in Datenbanktabellen verwendet
- Sie lassen sich leicht zwischen verteilten Systemen teilen und garantieren Eindeutigkeit
- Wegen ihrer Größe kann man an ihrer Eignung zweifeln, aber oft gibt es keine echte Wahl
UUID-Datentyp in PostgreSQL
-
UUIDs als Zeichenkette speichern
- PostgreSQL bietet zum Speichern von Zeichenketten den Datentyp
text - Der
text-Typ ist jedoch nicht gut geeignet, um UUIDs zu speichern - PostgreSQL bietet mit
uuideinen eigenen Datentyp für UUIDs - Der
uuid-Typ ist ein 128-Bit-Datentyp und benötigt 16 Byte pro Wert - Beim
text-Typ kommen 1 oder 4 Byte Overhead hinzu
- PostgreSQL bietet zum Speichern von Zeichenketten den Datentyp
-
Experimentelle Ergebnisse
- Zum Vergleich wurden zwei Tabellen erstellt: eine mit
text, die andere mituuid - Nach dem Einfügen von 10.000.000 Zeilen wurden Tabellen- und Indexgröße verglichen
- Die Tabelle mit
textwar 54 % größer, der Index sogar 85 % größer
- Zum Vergleich wurden zwei Tabellen erstellt: eine mit
UUIDs und B-Tree-Indizes
-
B-Tree-Indizes und UUIDs
- Zufällige UUIDs eignen sich nicht gut für B-Tree-Indizes
- B-Tree-Indizes arbeiten gut mit geordneten Werten
UUID.randomUUID()in Java gibt eine UUID v4 zurück, also einen pseudozufälligen Wert- UUID v7 erzeugt zeitlich sortierte Werte und ist daher besser für B-Tree-Indizes geeignet
-
Verwendung von UUID v7
- Um UUID v7 in Java zu verwenden, wird die Bibliothek
java-uuid-generatorbenötigt - Das Erzeugen von UUID v7 kann die Insert-Performance verbessern
- Um UUID v7 in Java zu verwenden, wird die Bibliothek
Einfluss von UUID v7 auf die INSERT-Performance
- Experiment
- Es wurde eine Tabelle mit UUID v7 erstellt, und zur Messung der Performance wurden 10-mal jeweils 10.000 Zeilen eingefügt
- Die Ergebnisse sind etwas zufällig, aber das Einfügen von UUID v7 ist etwa doppelt so schnell
Weiterführende Lektüre
- In PostgreSQL 17 könnte UUID v7 nativ unterstützt werden
- Informationen zum UUID-v7-Format
- Auswirkungen von UUIDs auf die Performance von Primärschlüsseln in Datenbanken
Zusammenfassung
-
Problem der UUID-Länge
- Selbst mit Optimierungen sind UUIDs nicht der optimale Typ für Primärschlüssel
- Wenn man die Wahl hat, sollte man andere Optionen wie TSID in Betracht ziehen
-
Notwendigkeit von Optimierungen
- Bei großen Datensätzen oder erwartet hohem Traffic sollte man Optimierungen in Betracht ziehen
- Einen Primärschlüssel später zu ändern ist schwierig, deshalb ist es wichtig, ihn von Anfang an richtig zu wählen
-
Hinweise
- Der Autor ist kein PostgreSQL-Experte, sondern teilt lediglich, was er gelernt hat
- Wer den Artikel nützlich fand, möge gern per Kommentar oder auf Twitter Feedback geben
Zusammenfassung von GN⁺
- Dieser Artikel behandelt effiziente Methoden, UUIDs in PostgreSQL als Primärschlüssel zu verwenden
- Experimente zeigen, dass UUID v7 die Insert-Performance verbessern kann
- Bei großen Datensätzen oder erwartet hohem Traffic sind Optimierungen wichtig
- Auch andere Optionen wie TSID sind einen Blick wert
4 Kommentare
Ist es zu viel verlangt, sich für
uuidstatt des Standardformats (Hexadezimal + Bindestriche) eine Base62-Kodierung zu wünschen?uuidv7 ist unbesiegbar
uuidv8+ ist ein „Gott“
Die größte Hürde ist, dass sie nicht menschenfreundlich sind … In vielen Bereichen brauche ich das immer noch.
Hacker-News-Kommentare
Es wird empfohlen,
bigserialals B-Tree-freundlichen Primärschlüssel zu verwenden und UUIDs, als String kodiert, als Option für externe Record-Locator in Betracht zu ziehenBeim Entwurf eines Datenbankschemas sollte man die Prinzipien der Trennung von Zuständigkeiten und der mechanischen Sympathie im Blick behalten
Die typisierten zufälligen IDs von Stripe sind in Wirklichkeit nicht zufällig
bigserial+HMAC-Locator bevorzugtIn Postgres sind zufällige UUIDs kein großes Problem
serial(4 Byte) oderbigserial(8 Byte), aber auf Ebene der gesamten Tabelle ist das kein großes ProblemBevor man in Postgres über
serialvs. zufällige UUID vs. geordnete UUID nachdenkt, gibt es viele andere Dinge, über die man sich Sorgen machen sollteKürzlich wurde ULID als Postgres-PK gewählt, und dieser Artikel war dabei sehr hilfreich: https://brandur.org/nanoglyphs/026-ids
ULID wird bevorzugt, weil es mit dem UUID-Typ kompatibel ist und einen eingebauten Zeitstempel hat, sodass eine Sortierung nach ID zugleich eine Sortierung nach Zeitstempel ist
Es wäre gut, auch
int64in den Vergleich aufzunehmen, um den Overhead von UUIDs gegenüber dem traditionellen Ansatz zu vergleichenEinfügeleistung ist eine schlechte Methode zur Leistungsbewertung
In SQLite wird UUID4 bevorzugt, weil die Wahrscheinlichkeit von Page-Cache-Kollisionen während Transaction-Locks geringer ist
Ganzzahlige autoinkrementierende Primärschlüssel werden bevorzugt
Das Benchmarking der Einfügezeit für UUIDv7 schließt die Zeit zur UUID-Erzeugung ein
Es ist unwahrscheinlich, dass PostgreSQL 17 Unterstützung für UUIDv7 enthalten wird
Es wurde begonnen,
python-ulidzu verwenden, und ULID ist UUID überlegenDa der Link zum UUID-v7-Standard veraltet ist, sollte RFC 9562 referenziert werden: https://datatracker.ietf.org/doc/html/rfc9562