Testing & QA · 6 Min. Lesezeit

UUID v4 vs. v7 in 2026: Bit-Layout, Sortierung, Indexkosten

UUID v4 vs. v7 anhand ihrer Bits erklärt: 122 zufällige Bits gegenüber einem 48-Bit-Millisekunden-Zeitstempel, Sortierverhalten, B-Tree-Indexkosten, Datenschutz und Kodierungsgröße.

Von Charlie Simmon ·

UUID v4 und UUID v7 sind beide 128-Bit-Bezeichner – und dort endet die Gemeinsamkeit. v4 verwendet 122 Bits für Zufälligkeit. v7 stellt einen 48-Bit-Unix-Millisekunden-Zeitstempel voran, gefolgt von 4 Versionsbits, 74 zufälligen Bits und 2 Variantenbits. Die Versionsnummer ist keine Rangfolge. Sie sagt aus, was der Bezeichner preisgeben darf und wie er sortiert.

Beide sind in RFC 9562 definiert, das 2024 RFC 4122 abgelöst hat. Die praktische Entscheidung läuft auf drei Fragen hinaus: Muss der Bezeichner nach Erstellungszeit sortiert werden, landet er in einem B-Tree-Primärschlüssel, und ist es akzeptabel, dass die Erstellungszeit für jeden lesbar ist, der den Wert besitzt. Dieser Leitfaden beantwortet diese Fragen anhand des Byte-Layouts statt mit einer Faustregel.

Das 128-Bit-Layout im direkten Vergleich

Jede UUID ist 16 Byte groß, und die Felder sind durch ihre Position definiert, nicht durch die Bindestriche im Text. Byte 6 enthält die Version in seinem oberen Nibble. Byte 8 enthält die Variante in seinen obersten zwei Bits. Alles andere hängt von der Version ab. In der kanonischen Zeichenkette ist das 13. Hexadezimalzeichen die Version und das 17. die Variante.

Bei v4 sind die 122 Bits, die nicht Version oder Variante sind, zufällig. Bei v7 sind die ersten 48 Bits der Unix-Zeitstempel in Millisekunden, Big-Endian, weshalb v7-Werte als Rohbytes in Erstellungsreihenfolge sortieren. Die verbleibenden 74 Bits sind standardmäßig zufällig, obwohl RFC 9562 erlaubt, dass einige davon einen Zähler für Monotonie innerhalb einer Millisekunde tragen.

FeldBitsv4v7
Bytes 0-548Zufälligunix_ts_ms, Big-Endian
Byte 6 oberes Nibble40100 (Version 4)0111 (Version 7)
Byte 6 unteres Nibble und Byte 712Zufälligrand_a
Byte 8 obere Bits210x-Variante10x-Variante
Bytes 8-15 verbleibend62Zufälligrand_b
Zufällige Bits insgesamt12212274

v4 im Detail

Eine v4-UUID ist eine Zufallszahl mit sechs festen Bits. Das obere Nibble von Byte 6 ist 0100, sodass das 13. Zeichen der kanonischen Zeichenkette immer 4 ist. Die obersten zwei Bits von Byte 8 sind 10, sodass das 17. Zeichen immer 8, 9, a oder b ist. Das sind die einzigen vorhersagbaren Zeichen; die anderen 30 Hexadezimalziffern sind zufällig.

Die Zufälligkeit ist die Sicherheitseigenschaft. Ein v4-Wert enthält keinen Zeitstempel, keine Sequenz und keine Maschinenkennung, verrät also nichts darüber, wann oder wo er erzeugt wurde. Das macht ihn zu einer vernünftigen Wahl für einen öffentlichen Bezeichner, der nicht aufzählbar sein darf, sofern er aus einer kryptografisch sicheren Zufallsquelle stammt. Ein 122-Bit-Raum macht Kollisionen vernachlässigbar: Eine Milliarde Werte ergibt eine Kollisionswahrscheinlichkeit von etwa 2^-63.

  • Versions-Nibble: immer 4 an Position 13 der kanonischen Zeichenkette
  • Variante: immer 8, 9, a oder b an Position 17
  • Zufällige Bits: 122, aus einem CSPRNG
  • Sortiert nach nichts Bedeutendem; die Reihenfolge ist zufällig
  • Verrät weder Erstellungszeit noch Sequenz

v7 im Detail

Eine v7-UUID ist zeitgeordnet. Die Bytes 0 bis 5 enthalten die Anzahl der Millisekunden seit der Unix-Epoche, Big-Endian. Das obere Nibble von Byte 6 ist 0111. Das untere Nibble von Byte 6 und das gesamte Byte 7 bilden rand_a, die obersten zwei Bits von Byte 8 sind die Variante, und die verbleibenden 62 Bits sind rand_b. Das sind 74 zufällige Bits plus ein Zeitstempel, der durch bloßes Ansehen lesbar ist.

Der Zeitstempel ist 48 Bit lang, was für Millisekunden bis zum Jahr 10889 ausreicht, sodass ein Überlauf kein praktisches Problem darstellt. Zwei v7-Werte, die in derselben Millisekunde erzeugt wurden, unterscheiden sich nur in ihren zufälligen Bits oder Zählerbits, und ein später erzeugter Wert vergleicht sich als Byte-String immer größer als ein früher erzeugter, solange die Uhr nicht rückwärts läuft. Diese Ordnung ist der ganze Sinn der Sache.

ByteInhaltBeispiel
0-5Unix-Millisekunden, Big-Endian0192f3c4a1b2
6 oberes NibbleVersion 77
6 unteres Nibble + 7rand_a, 12 Bitsa1b
8 oberste 2 BitsVariante 108, 9, a oder b
8 (untere 6) bis 15rand_b, 62 BitsZufällig oder Zähler

Sortierung und Monotonie innerhalb einer Millisekunde

Die lexikografische Sortierung der kanonischen Textform entspricht der Byte-Reihenfolge, weil die Bindestriche an festen Positionen stehen und Hexadezimalziffern in derselben Reihenfolge sortieren wie ihre Werte, wenn sie kleingeschrieben sind. Sortiert man nach der Textform oder nach den 16 Bytes, erhält man die Erstellungsreihenfolge. Das gilt maschinenübergreifend ohne Koordination, weshalb v7 für Ereignisprotokolle und für Bezeichner, die Teil eines Sortierschlüssels werden, attraktiv ist.

Die Lücke liegt innerhalb einer einzelnen Millisekunde. Standardmäßig werden zwei in derselben Millisekunde erzeugte Werte nach ihren zufälligen Bits geordnet, was nicht der Erstellungsreihenfolge entspricht. RFC 9562 beschreibt die Verwendung des rand_a-Felds oder der linkesten zufälligen Bits als Zähler, der bei jedem Zeitstempel-Tick zufällig initialisiert wird. Mit dieser Methode sind Werte für praktische Zwecke innerhalb einer Millisekunde monoton, auf Kosten von etwas weniger Zufälligkeit und einem gemeinsamen Zähler, der von gleichzeitigen Erzeugern sorgfältig behandelt werden muss.

  • Über Millisekunden hinweg: Die Ordnung ist garantiert, solange die Uhr monoton ist
  • Innerhalb einer Millisekunde: zufällige Reihenfolge, sofern kein Zähler verwendet wird
  • Zähler-Methode: pro Tick zufällig initialisieren, pro Wert inkrementieren
  • Uhr-Rücklauf: kann die Ordnung brechen, daher eine monotone Uhrquelle verwenden
  • Nebenläufigkeit: Den Zähler atomar inkrementieren, sonst geht die Eigenschaft verloren

Indexkosten in einem B-Tree

Ein zufälliger v4-Primärschlüssel wird an einer zufälligen Position im Index eingefügt. In einem B-Tree bedeutet das, bei fast jedem Einfügen eine andere Blattseite anzufassen, Seiten aus dem Buffer-Pool zu verdrängen und Seiten in der Mitte zu teilen, wodurch sie halb voll zurückbleiben. Der Index wächst, die Write Amplification steigt, und die Cache-Trefferquote sinkt, je größer die Tabelle wird.

Ein v7-Schlüssel wird nahe der rechten Kante eingefügt, sodass das Arbeits-Set klein bleibt und Seitenteilungen am Ende stattfinden, wo sie günstig sind. Der Kompromiss ist Konkurrenz: Jeder Schreiber will dieselbe rechteste Seite. Bei einer einzelnen Datenbank ist das mit einigen hundert Schreibvorgängen pro Sekunde meist in Ordnung; bei sehr hoher Nebenläufigkeit wird es zum Hotspot, und die üblichen Gegenmaßnahmen sind Batching, Verschachtelung auf Verbindungsebene oder ein wenig Jitter in den hohen Bits.

EigenschaftZufälliger v4-SchlüsselZeitgeordneter v7-Schlüssel
EinfügepositionZufällige BlattseiteRechteste Blattseite
SeitenteilungenHäufig, mitten auf der SeiteSelten, am Ende
Buffer-Pool-LokalitätSchlecht bei großen IndizesGut
IndexgrößeGrößer, geringerer FüllgradKompakt
Schreib-HotspotÜber den Baum verteiltAuf die rechte Kante konzentriert
Bereichsscan nach ZeitErfordert eine separate SpalteNativ

Datenschutz und das Preisgeben des Zeitstempels

Ein v7-Wert verrät jedem, der ihn besitzt, ungefähr, wann er erzeugt wurde – auf die Millisekunde genau – und damit, wie viele andere Datensätze rund um diesen Zeitpunkt erzeugt wurden. Das ist für interne Schlüssel und Ereignis-IDs in Ordnung. Es ist nicht in Ordnung für einen öffentlichen Bezeichner, der weder Anmeldevolumen noch Bestellrate noch das Alter eines Kontos preisgeben soll.

Wenn Sie sowohl Ordnung als auch Undurchsichtigkeit benötigen, besteht die Wahl darin, v7 intern zu halten und eine separate zufällige öffentliche ID herauszugeben oder v4 für alles zu verwenden, was Ihr System verlässt. Betrachten Sie eine UUID in keiner der beiden Versionen als Capability-Token; beide sind Bezeichner, keine Autorisierung. Eine v4-ID ist in der Praxis nicht erratbar, muss aber trotzdem bei jeder Anfrage gegen die Zugriffskontrolle geprüft werden.

  • v7 verrät die Erstellungszeit auf die Millisekunde genau
  • Das Aufzählen benachbarter v7-Werte verrät das Datensatzvolumen
  • v7 intern halten, v4 oder eine separate öffentliche ID herausgeben
  • Keine der beiden Versionen ist ein Zugriffstoken oder ein Geheimnis
  • Randomisiertes v7 gibt es nicht; der Zeitstempel ist obligatorisch

Speicher- und Kodierungsgröße

Sechzehn Bytes ist die Speicherantwort für beide Versionen. Die kanonische Textform hat 36 Zeichen, davon 32 Hexadezimalziffern und 4 Bindestriche. Das Speichern der Textform verdoppelt die Größe und verlangsamt Vergleiche, daher einen nativen UUID-Typ verwenden, wo es einen gibt, BINARY(16), wo es keinen gibt, und nur an der Grenze formatieren.

SQL Server hat eine Eigenheit, die es zu testen lohnt: Sein uniqueidentifier-Typ sortiert in einer Byte-Reihenfolge, die nicht mit der kanonischen Zeichenkette übereinstimmt, und die interne Byte-Reihenfolge weicht von RFC 4122 ab. Code, der sich auf die v7-Ordnung verlässt, muss das Sortierverhalten auf dieser Plattform überprüfen, statt es anzunehmen. Wo Sie eine kompakte Textform benötigen, ergibt base64url ohne Padding 22 Zeichen, aber es ist keine standardkonforme UUID-Darstellung und wird Werkzeuge verwirren, die die kanonische Form erwarten.

DarstellungGrößeHinweise
Binär16 BytesNative Speicherung, schnellster Vergleich
Kanonischer Text36 Zeichen8-4-4-4-12 mit Bindestrichen
Hex ohne Bindestriche32 ZeichenWird in einigen APIs und Logs verwendet
Base64url, ohne Padding22 ZeichenKeine standardkonforme UUID-Form
Base3226 ZeichenSelten, wird von einigen Ticketsystemen verwendet

Auswählen, migrieren und testen

Wählen Sie v7, wenn der Bezeichner ein Datenbankschlüssel ist, wenn Sie nach Erstellungszeit sortieren möchten, ohne eine zweite Spalte zu benötigen, oder wenn Sie eine stark schreiblastige Tabelle aufbauen. Wählen Sie v4, wenn der Wert öffentlich preisgegeben wird, wenn die Erstellungszeit sensibel ist oder wenn das System bereits eine Zeitstempelspalte speichert und von der Ordnung nichts gewinnt. Beide sind für unterschiedliche Randbedingungen die richtige Wahl, und sie in einer Tabelle zu mischen ist meist ein Fehler.

Tests müssen die Struktur prüfen, nicht die Werte. Prüfen Sie das Versions-Nibble, das Varianten-Nibble und die Bytelänge nach dem Parsen. Bei v7 prüfen Sie, dass der eingebettete Zeitstempel im Testfenster liegt und dass zwei in Reihenfolge erzeugte Werte korrekt vergleichen. Speichern Sie niemals eine literale UUID als Snapshot in einem Test, und prüfen Sie niemals, dass eine v7 strikt größer als die vorherige ist, es sei denn, der Generator verwendet einen Zähler; ohne einen ist die Reihenfolge innerhalb derselben Millisekunde zufällig.

SituationBevorzugenGrund
Primärschlüssel in einer großen Tabellev7Lokalität und kleinerer Index
Öffentlich sichtbarer Bezeichnerv4Keine Preisgabe des Zeitstempels
Nach Zeit sortiertes Ereignisprotokollv7Native Ordnung ohne zusätzliche Spalte
Sitzungs- oder Reset-TokenKeines von beidenEin zweckgebundenes Zufallstoken verwenden
Bestehende Tabelle mit Zeitspaltev4Ordnung ist bereits verfügbar
Systemübergreifender AustauschBeideBeide sind standardkonforme 128-Bit-UUIDs

Fragen

Sind UUID v4 und v7 gleich groß?+
Ja. Beide sind 128 Bit, 16 Byte und 36 Zeichen in kanonischer Textform. Nur das interne Layout unterscheidet sich.
Sortiert UUID v7 korrekt?+
Über Millisekunden hinweg ja, als Rohbytes und als kanonischer Text. Innerhalb einer einzelnen Millisekunde ist die Standardreihenfolge zufällig, sofern der Generator keinen Zähler verwendet.
Welche ist besser für einen Datenbank-Primärschlüssel?+
v7, weil Einfügungen nahe der rechten Kante des B-Trees bleiben, statt über ihn zu streuen. Der Kompromiss ist ein Schreib-Hotspot auf der letzten Seite bei sehr hoher Nebenläufigkeit.
Gibt UUID v7 Informationen preis?+
Sie verrät die Erstellungszeit auf die Millisekunde genau, und benachbarte Werte verraten das Datensatzvolumen. Halten Sie sie intern oder verwenden Sie v4 für Bezeichner, die Ihr System verlassen.
Kann ich eine UUID als Zugriffstoken verwenden?+
Nein. Eine UUID ist ein Bezeichner. Selbst ein v4-Wert muss bei jeder Anfrage gegen die Zugriffskontrolle geprüft werden, und ein Token sollte aus einem zweckgebundenen Generator mit eigenen Lebensdauerregeln stammen.

Beispiele sind synthetisch. Verwenden Sie eine generierte Adresse nicht für Identitätsprüfungen, Kontoregistrierungen oder Lieferungen.

Referenzstandards

Als Nächstes lesen

Alle Ratgeber