Cloud allgemein

Data Partitioning: Range, List, Hash und Hive-Style im Praxisvergleich

Deine Query scannt 900 GB für 2.000 Zeilen. Fix ist kein größerer Cluster, sondern die Partitioning-Strategie. Vier Pattern, klare Trade-Offs und Pruning-Killer.

Harbinger Team14. Mai 20264 Min. LesezeitAktualisiert 14.5.2026
  • partitioning
  • data-engineering
  • spark
  • hive
  • sql
  • performance
  • lakehouse
Inhaltsverzeichnis10 Abschnitte

Deine Query scannt 900 GB, um 2.000 Zeilen zurückzugeben. Der Fix ist kein größerer Cluster — es ist eine Partitionierungsstrategie, die du wahrscheinlich übersprungen hast.

TL;DR

  • Partitioning organisiert Daten physisch, damit Queries nur die relevanten Slices anfassen.
  • Vier Pattern: Range (Zeit), List (Kategorien), Hash (gleichmäßige Verteilung), Hive-Style (Directories).
  • Filter-Spalte sollte in >80 % deiner WHERE-Klauseln vorkommen.
  • Funktionen auf der Partitions-Spalte killen Pruning.
  • Über-Partitionierung killt Performance — Planning > Execution.

Was Partitioning ist

Partitioning teilt ein Dataset in kleinere, unabhängige Units — Partitions — basierend auf Spaltenwerten. Die Engine liest nur die relevanten Partitions = Partition Pruning.

StrategieWie sie splittetBest für
RangeWert in definiertem BereichDatums, Time-Series, sequenzielle IDs
ListWert matched explizite SetCountry-Codes, Kategorien, Status
HashHash modulo N BucketsHigh-Cardinality ohne Natural Range

Hive-Style ist eine Directory-Naming-Convention von Spark, Hive, Lakehouses — layert auf die Strategien.

Range-Partitioning

Häufigste Form: Partition nach Datum.

CREATE TABLE orders (
    order_id BIGINT,
    customer_id BIGINT,
    order_date DATE,
    amount NUMERIC
) PARTITION BY RANGE (order_date);

CREATE TABLE orders_2024_q1 PARTITION OF orders
    FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');

CREATE TABLE orders_2024_q2 PARTITION OF orders
    FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');

Bei WHERE order_date BETWEEN '2024-06-01' AND '2024-06-30' liest der Planner nur orders_2024_q2.

Trade-Offs:

  • Exzellent für Time-Series und Date-Bound Reporting
  • Einfach altes zu archivieren (Partition droppen statt Millionen Rows)
  • Anfällig für Partition-Skew bei ungleicher Verteilung
  • Schwach für Point-Lookups auf Non-Partition-Columns

List-Partitioning

Routet jede Zeile zu einer Partition basierend auf diskretem Wert. Gut bei Low-Cardinality.

CREATE TABLE sales (
    sale_id BIGINT,
    region TEXT,
    product_id INT,
    revenue NUMERIC
) PARTITION BY LIST (region);

CREATE TABLE sales_europe PARTITION OF sales
    FOR VALUES IN ('DE', 'FR', 'NL', 'ES', 'IT', 'AT', 'CH');

CREATE TABLE sales_americas PARTITION OF sales
    FOR VALUES IN ('US', 'CA', 'BR', 'MX');

Trade-Offs:

  • Saubere Isolation logischer Datendomänen
  • Einfache Per-Region-Access-Controls und Maintenance-Fenster
  • Neue Werte = DDL-Changes
  • Sinnlos, wenn Queries nicht auf der Partition-Spalte filtern

Hash-Partitioning

Hashfunktion auf Spaltenwert, Routing zu hash(value) % N. Keine natürliche Order, nur gleichmäßige Verteilung.

CREATE TABLE events (
    event_id BIGINT,
    customer_id BIGINT,
    event_type TEXT,
    created_at TIMESTAMPTZ
) PARTITION BY HASH (customer_id);

CREATE TABLE events_p0 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE events_p1 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE events_p2 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE events_p3 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 3);

Hash gibt dir gleichmäßige Verteilung, hilft aber nicht bei Range-Queries — WHERE customer_id > 100000 scannt alle vier.

Trade-Offs:

  • Verhindert Skew, gut für Parallel-Processing und Write-Throughput
  • Kein Pruning für Range-Filter
  • Repartitioning (N ändern) = Full-Rewrite

Hive-Style-Partitioning

Directory-Naming-Convention statt Algorithmus. Daten in Folder-Hierarchie mit Partitions-Werten:

s3://my-bucket/events/
├── year=2024/
│   ├── month=01/
│   │   ├── day=01/
│   │   │   └── part-00000.parquet
│   │   └── day=02/
│   └── month=02/
└── year=2025/

Spark, Hive, Trino, Athena, DuckDB unterstützen das nativ.

df.write \
    .mode("overwrite") \
    .partitionBy("year", "month", "day") \
    .parquet("s3://my-bucket/events/")

spark.read \
    .parquet("s3://my-bucket/events/") \
    .filter("year = 2024 AND month = 1")

Klassischer Fehler: Partition nach High-Cardinality-Spalte wie user_id. 10 Mio. User = 10 Mio. Directories. File-System-Overhead killt Performance. Faustregel: DISTINCT count < ~10.000.

Trade-Offs:

  • Portabel (Spark, Athena, Trino, DuckDB, Hive)
  • Menschlich lesbar
  • Inkrementelle Writes ohne Full-Rewrite
  • Small-Files-Problem
  • Metadata-Overhead bei zu vielen Partitions

Welche Strategie wann?

SzenarioEmpfehlung
Time-Series / Append-by-DateRange (Datum) + Hive-Style
Multi-Region-ReportingList (Region)
High-Cardinality-Join-KeysHash
Lakehouse auf Object StorageHive-Style (Range oder List darunter)
Große Parallel-LoadsHash
DSGVO-Löschung nach RegionList (Partition droppen = nach Region löschen)

Heuristik: Die Spalte, nach der du partitionierst, sollte in >80 % deiner WHERE-Klauseln auftauchen.

Pruning-Killer

-- PRUNING WORKS — direkter Equality-Filter
SELECT * FROM events WHERE year = 2024 AND month = 3;

-- PRUNING FAILS — Funktion auf der Partition-Spalte
SELECT * FROM events WHERE YEAR(created_at) = 2024;

-- PRUNING FAILS — nicht-deterministischer Ausdruck
SELECT * FROM events WHERE created_at > NOW() - INTERVAL 30 DAYS;

Wenn deine Partition-Spalten year/month/day als Integer sind: filtere gegen Integers, nicht abgeleitete Ausdrücke.

Über-Partitioning

Mehr Partitions ist nicht besser. Jede ist ein Metadata-Eintrag, jede Hive-Style-Partition ein Directory-Listing. 500.000 Partitions = Planning-Overhead schlägt Scan-Ersparnis.

Zeichen für Über-Partitioning:

  • Query-Planning dauert länger als Execution
  • Viele Partitions mit < 10 MB Daten
  • Filezahl wächst schneller als Datenvolumen

Fix: Partition Coarsening (täglich statt stündlich) oder File Compaction (OPTIMIZE in Spark, Delta Auto-Optimize).

FAQ

Wie viele Partitions sind zu viele? Hängt vom Engine ab. Spark/Hive vertragen Tausende, brechen bei Hunderttausenden ein. DuckDB hat keine harten Grenzen, aber Listing-Cost auf S3 wird teuer.

Hash + Range kombinieren? Geht (Composite Partitioning). Komplexer zu managen, lohnt sich nur bei massiven Tables.

Wann lohnt sich Partitioning gar nicht? Tables unter ~1 GB. Da kostet das Management mehr als der Scan.

Was hat das mit DSGVO zu tun? Mit List-Partition nach country kannst du DSGVO-Löschungen einer ganzen Region per Partition-Drop machen statt millionenfach UPDATE/DELETE.

Stand: 14. Mai 2026.

H

Geschrieben von

Harbinger Team

Cloud-, Data- und AI-Engineer in DACH. Schreibt seit 2018 über infrastruktur­kritische Tech-Entscheidungen — keine Marketing- Folien, sondern echte Trade-offs aus Production-Workloads.

Hat dir das geholfen?

Jede Woche ein neuer Artikel über DACH-Cloud, Data und AI — direkt in dein Postfach. Kein Spam, kein Marketing-Sprech.

Kein Spam. 1-Klick-Abmeldung. Datenschutz bei Loops.so.