Db2 LUW: Performance von UUIDs als Primärschlüssel

Veröffentlicht 23.12.2024

tl;dr

Motivation

In einer meiner Schulungen zu DB2 kam die Frage auf, ob sich die Art von UUIDs auf die Performance der Datenbank auswirkt. Also ob man besser zufällige oder sortierbare UUIDs nutzen sollte.

Für PostgreSQL kannte ich die Antwort: Dort müssen Primärschlüssel eine Ordnung aufweisen, damit der B-Tree des Indexes seltener neu balanciert werden muss.

Wie sich das jedoch bei DB2 verhält, wusste ich nicht. Meine Vermutung war aber, dass dort ein ähnlicher Effekt zu beobachten sein sollte.

Über UUIDs

Seit Mai 2024 gibt es einen neuen RFC Standard, der sich mit verschiedenen Arten von UUIDs beschäftigt.

Für Primärschlüssel kommen im Wesentlichen zwei Varianten infrage: Die Frage lautet also: "Wenn ich UUIDs als Primärschlüssel in DB2 verwende, sollte ich UUIDv4 oder UUIDv7 nehmen?"

Testaufbau

Diese Frage hat mich neugierig gemacht, und ich habe beschlossen, das Ganze genauer zu untersuchen.

Um der Sache auf den Grund zu gehen, habe ich ein Testsetup als Spring Boot Anwendung erstellt. Damit fülle ich zunächst eine Tabelle mit einigen Daten und anschließend messe ich, wie lange ein Batch INSERT von 100.000 Zeilen benötigt. Das Ganze einmal mit UUIDv4 als Primärschlüssen und einmal mit UUIDv7.

In Java können UUIDv4 direkt über UUID.randomUUID() erzeugt werden. Für eine UUIDv7 muss man aktuell noch eine Library einbinden oder selbst etwas Code schreiben.

Der Code zum Einfügen der Daten sieht in etwa so aus:
public void insertBatchJdbcClient(List<User> users, int batchSize) {
    jdbcTemplate
        .batchUpdate("""
            INSERT INTO test_user (id, username, password)
            VALUES (?, ?, ?);
            """,
            users, batchSize,
            (ps, argument) -> {
                ps.setObject(1, argument.id());
                ps.setString(2, argument.username());
                ps.setString(3, argument.password());
            });
}

Teil I: PostgreSQL

Bei PostgreSQL konnte ich bekannte Ergebnisse reproduzieren: UUIDv4 (random): Zufällig Verteilung der Schlüssel erschwerte dem B-Tree-Index die Arbeit. UUIDv7 (zeitlich geordnet): Reduziert die Neubalancierung des Indexes merklich und lieferte deutlich bessere Performance. PostgreSQL performance

Als Datentyp für den Primärschlüssel habe ich UUID verwendet.

Teil II: DB2

Auch bei DB2 zeigte sich der erwartete Effekt - wenngleich auch weniger stark als bei PostgreSQL. DB2 performance

Als Datentyp für den Primärschlüssel habe ich CHAR(16) FOR BIT DATA verwendet.

Fazit

UUIDv7 bietet nicht nur bei PostgreSQL, sondern auch bei DB2 Performancevorteile – wenngleich auch diese geringer ausfallen.

In neuen Code sollte somit auf UUIDv7 als Primärschlüssel gesetzt werden, falls man sich generell entscheidet UUIDs zu verwenden. Für Insert-lastige Workloads kann sich dadurch ein erkennbarer Performancevorteil ergeben.

Ob man bestehende Tabellen und Code von einer anderen Art UUID auf UUIDv7 umstellen sollte, hängt vom Aufwand und vom Workload auf den Daten ab.

Für Anmerkungen oder Feedback schreibt mir gerne unter info (at) leonardw (punkt) de

Kleingedrucktes

Folgendes Setup habe ich für die Tests verwendet.

Server DB2 PostgreSQL Java 21 (Temurin), Spring Boot 3.4