← Alle Artikel
TechnologieDaten

JSONB in PostgreSQL: Kampfhistorien ohne Joins

Borzsport Redaktion · Datenanalyse & Technologie12. März 20266 Min. Lesezeit

Normal vs. Denormal

Klassische Datenbanktheorie (Codd, 1970): Jeder Datenpunkt genau einmal. Für Kampfhistorien hieße das: fights-Tabelle mit FK auf fighters. Jeder Abruf = JOIN. Bei 1200+ Fightern mit je 10+ Kämpfen = langsam.

JSONB-Vorteile

Normalisiert (fights-Tabelle)Denormalisiert (JSONB)
JOIN für jeden AbrufEin SELECT reicht
Schema-Migration für neue FelderFlexible Felder jederzeit
Referentielle IntegritätKein FK-Overhead
Komplexe QueriesJS-Array-Operationen
Schnell bei AggregationenSchnell bei Einzelabruf

Analytics über Arrays

Die api/analytics.js zeigt, wie man Statistiken über JSONB in reinem JavaScript berechnet:

fighters.flatMap(f => parseFights(f.tapology_fights))
  .filter(fight => fight.result !== 'C')
  .reduce((acc, fight) => { ... }, {})

flatMap zum Unnesten, reduce für Aggregationen, Map für Gruppierungen. Kein SQL nötig.

Ein echtes tapology_fights Objekt

So sieht ein einzelner Kampfeintrag im JSONB-Array aus. Klick dich durch die Struktur:

INTERAKTIV

tapology_fights — JSON Explorer

Klicke auf Objekte um sie auf- und zuzuklappen. Wähle einen Kampf aus:

{
"result": "W"
,
"opponent": "Max Mustermann"
,
"event": "Austrian MMA Championship 2025"
,
"date": "2025-11-15"
,
"method": "TKO (Punches)"
,
"round": 2
,
"fight_time": "3:41"
,
"sport": "MMA"
,
"weight_class": "Lightweight"
}

💡 Jeder Kämpfer hat ein JSONB-Array von Kampfeinträgen in dieser Struktur — kein separater Table, kein JOIN.

Denormalisierung ist kein Antipattern — es ist ein bewusstes Trade-off zugunsten von Leseperformance und API-Einfachheit.