UUID Vs Auto Increment IDs
UUID vs. Auto-Increment: ID-Strategien
Die Wahl der ID-Strategie beeinflusst Skalierung und Architektur. Vergleichen Sie UUIDs mit Auto-Increment IDs.
Vergleich
| Aspekt | Auto-Increment | UUID |
|---|---|---|
| Größe | 4-8 Bytes | 16 Bytes (36 Zeichen) |
| Lesbarkeit | Gut (1, 2, 3) | Schlecht |
| Vorhersagbar | Ja ⚠️ | Nein ✓ |
| Verteilte Systeme | Problematisch | Ideal |
| Index-Performance | Optimal | Schlechter (v4) |
Auto-Increment
-- MySQL
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);
-- PostgreSQL
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255)
);
-- Oder mit IDENTITY (SQL Standard)
CREATE TABLE users (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255)
);
-- Vorteile:
-- ✅ Kompakt, schnelle JOINs
-- ✅ Natürliche Sortierung (ältere IDs zuerst)
-- ✅ Einfach zu debuggen
-- ✅ Optimale B-Tree Performance
-- Nachteile:
-- ❌ Enumeration Attack (ID erraten)
-- ❌ Information Disclosure (Anzahl User sichtbar)
-- ❌ Schwierig bei verteilten Systemen
-- ❌ Merge-Konflikte bei Multi-Master
UUID
-- PostgreSQL (native UUID)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(255)
);
-- Oder mit gen_random_uuid() (PostgreSQL 13+)
CREATE TABLE users (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name VARCHAR(255)
);
-- MySQL 8+
CREATE TABLE users (
id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
name VARCHAR(255)
);
-- Oder BINARY(16) für bessere Performance
CREATE TABLE users (
id BINARY(16) PRIMARY KEY,
name VARCHAR(255)
);
UUID Versionen
UUID v1: Zeit + MAC-Adresse 550e8400-e29b-11d4-a716-446655440000 → Zeitbasiert, sortierbar, aber MAC leakt UUID v4: Zufällig 550e8400-e29b-41d4-a716-446655440000 → Am gebräuchlichsten, nicht sortierbar UUID v7 (neu): Zeit + Zufällig 01889c89-df6b-7f1c-a03e-85998e4bb5d8 → Sortierbar + Zufällig → Beste für DBs!
ULID & andere Alternativen
# ULID (Universally Unique Lexicographically Sortable Identifier)
01ARZ3NDEKTSV4RRFFQ69G5FAV
# Struktur:
# 48 Bit: Timestamp (ms)
# 80 Bit: Zufällig
# Vorteile:
# ✅ Sortierbar (nach Zeit)
# ✅ URL-safe (keine -, keine /)
# ✅ Kompakter als UUID (26 Zeichen)
# ✅ Gute Index-Performance
# Node.js
npm install ulid
import { ulid } from 'ulid';
const id = ulid(); // 01ARZ3NDEKTSV4RRFFQ69G5FAV
# Andere Alternativen:
# - NanoID: ~21 Zeichen, URL-safe
# - KSUID: K-Sortable UID
# - Snowflake: Twitter's ID-Format
Best Practices
# Option 1: Interne Auto-Increment + Externe UUID
CREATE TABLE users (
id SERIAL PRIMARY KEY, -- Interner PK
public_id UUID UNIQUE NOT NULL, -- Externe Referenz
name VARCHAR(255)
);
-- API gibt nur public_id zurück
-- JOINs intern mit Integer-ID (schnell)
-- Keine Enumeration möglich
# Option 2: UUID v7 für alles
CREATE TABLE users (
id UUID DEFAULT gen_uuid_v7() PRIMARY KEY,
name VARCHAR(255)
);
-- Sortierbar + Nicht vorhersagbar
-- Gute Index-Performance
Code-Beispiele
// Node.js: UUID v4
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
// UUID v7 (neu)
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7(); // Zeitbasiert + sortierbar
// NanoID
import { nanoid } from 'nanoid';
const id = nanoid(); // 'V1StGXR8_Z5jdHi6B-myT'
// PHP
$uuid = \Ramsey\Uuid\Uuid::uuid4()->toString();
// Python
import uuid
id = str(uuid.uuid4())
Wann was verwenden?
Auto-Increment wenn:
- Einzelne Datenbank
- IDs nur intern verwendet
- Performance kritisch
- Keine Sicherheitsbedenken
UUID/ULID wenn:
- Verteilte Systeme / Microservices
- IDs in URLs / öffentlich sichtbar
- Client-seitige ID-Generierung
- Daten-Synchronisation zwischen DBs