682 lines
15 KiB
Markdown
682 lines
15 KiB
Markdown
|
|
---
|
|||
|
|
theme: seriph
|
|||
|
|
title: Ringstats – Zwischenpräsentation
|
|||
|
|
info: |
|
|||
|
|
## Ringstats
|
|||
|
|
Zwischenstandspräsentation – Moderne Datenbanken
|
|||
|
|
Justin Rost · Michelle Reichelt · Yasin Ergün
|
|||
|
|
class: text-center
|
|||
|
|
transition: slide-left
|
|||
|
|
mdc: true
|
|||
|
|
fonts:
|
|||
|
|
sans: Inter
|
|||
|
|
mono: Fira Code
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Ringstats
|
|||
|
|
Eine Live Datenbank für Elden Ring
|
|||
|
|
|
|||
|
|
<div class="pt-6 opacity-80 text-lg">
|
|||
|
|
Justin Rost · Michelle Reichelt · Yasin Ergün
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-10 opacity-60 text-sm">
|
|||
|
|
Zwischenpräsentation · Moderne Datenbanken · 08.06.2026
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: center
|
|||
|
|
class: text-center
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Inhalt
|
|||
|
|
|
|||
|
|
<div class="flex justify-center items-stretch gap-3 pt-14">
|
|||
|
|
|
|||
|
|
<div class="w-36 p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">🎯</div>
|
|||
|
|
<div class="pt-3 font-semibold text-sm">Szenario</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="flex items-center text-2xl opacity-40">⮀</div>
|
|||
|
|
|
|||
|
|
<div class="w-36 p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">🗺️</div>
|
|||
|
|
<div class="pt-3 font-semibold text-sm">ER-Modell</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="flex items-center text-2xl opacity-40">⮀</div>
|
|||
|
|
|
|||
|
|
<div class="w-36 p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">🧩</div>
|
|||
|
|
<div class="pt-3 font-semibold text-sm">Drei Modelle</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="flex items-center text-2xl opacity-40">→</div>
|
|||
|
|
|
|||
|
|
<div class="w-36 p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">⚖️</div>
|
|||
|
|
<div class="pt-3 font-semibold text-sm">Vergleich</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="flex items-center text-2xl opacity-40">→</div>
|
|||
|
|
|
|||
|
|
<div class="w-36 p-5 rounded-xl bg-red-400/10">
|
|||
|
|
<div class="text-4xl">✅</div>
|
|||
|
|
<div class="pt-3 font-semibold text-sm">Auswahl</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- kurzer Fahrplan durch die Präsentation
|
|||
|
|
- erst Szenario, dann ER-Modell als Grundlage
|
|||
|
|
- drei NoSQL-Modelle an unseren Daten zeigen
|
|||
|
|
- vergleichen und am Ende eine Auswahl treffen
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: center
|
|||
|
|
class: text-center
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Die Idee
|
|||
|
|
|
|||
|
|
<div class="opacity-70 pt-2">Eine Schnittstelle zwischen Spiel und Datenbank</div>
|
|||
|
|
|
|||
|
|
<div class="flex justify-center items-center gap-6 pt-12">
|
|||
|
|
|
|||
|
|
<div class="w-44 p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-5xl">🎮</div>
|
|||
|
|
<div class="pt-3 font-semibold">Spiel</div>
|
|||
|
|
<div class="pt-1 text-xs opacity-70">liest Position, Leben, Ausrüstung live aus</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="text-3xl opacity-40">⇄</div>
|
|||
|
|
|
|||
|
|
<div class="w-44 p-6 rounded-xl bg-red-400/10">
|
|||
|
|
<div class="text-5xl">🗄️</div>
|
|||
|
|
<div class="pt-3 font-semibold">Datenbank</div>
|
|||
|
|
<div class="pt-1 text-xs opacity-70">speichert und liefert passende Infos</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="text-3xl opacity-40">⇄</div>
|
|||
|
|
|
|||
|
|
<div class="w-44 p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-5xl">🌐</div>
|
|||
|
|
<div class="pt-3 font-semibold">Browser</div>
|
|||
|
|
<div class="pt-1 text-xs opacity-70">gleiche Daten parallel abrufbar</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Schnittstelle zwischen Spiel und Datenbank
|
|||
|
|
- Im Spiel werden Daten ausgelesen
|
|||
|
|
- Daten werden an Server gesendet und in DB verwalten
|
|||
|
|
- Programm und Browser lesen Daten aus
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Kernidee: Hilfe für Spieler
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-2 gap-6 pt-10 text-center">
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">🎮</div>
|
|||
|
|
<div class="pt-3 font-semibold">Im-Spiel Anzeige</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-80">zeigt z.B. Bossangriffe live und Checkliste</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-4xl">🖥️</div>
|
|||
|
|
<div class="pt-3 font-semibold">Browser App</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-80">Generelle Informationen und Analysen</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-8 text-center opacity-70">
|
|||
|
|
Es muss extrem schnell gehen, ohne spürbare Verzögerung.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Die Kernidee ist Hilfe für den Spieler
|
|||
|
|
- Im Spiel wird Oberfläche angezeigt mit Informationen
|
|||
|
|
- Browser App zeigt detaillreicher Infos zum Spieler und Welt
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Anwendungsfälle
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-3 gap-6 pt-12 text-center">
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-5xl">⚔️</div>
|
|||
|
|
<div class="pt-4 font-semibold">Bosskampf</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Fenster mit Resistenzen und Angriffe</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-5xl">📦</div>
|
|||
|
|
<div class="pt-4 font-semibold">Live-Standort</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Checkliste, Truhen und Objekte in der Nähe</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="text-5xl">🌐</div>
|
|||
|
|
<div class="pt-4 font-semibold">Website</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Builds und Statistiken</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Einige Informationen sind:
|
|||
|
|
- Resistenzen und Angriffe von Bossen
|
|||
|
|
- Truhen, Objekte und Checklisten in der Nähe
|
|||
|
|
- Detaillierte Informationen zu Statistiken und Builds auf Website
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Das ER-Modell
|
|||
|
|
|
|||
|
|
<div class="flex justify-center pt-2">
|
|||
|
|
<img src="/er-modell.png" class="h-100 rounded-lg bg-white p-2" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Zentrale Entity ist Player/Spieler
|
|||
|
|
- Grear (Inventar) beinhaltet (Weapon, Armor, Shield, Talisman).
|
|||
|
|
- Das sind alles Items, werden von Gegnern fallengelassen.
|
|||
|
|
- In Regionen sind Player, Enemies und Items
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: center
|
|||
|
|
class: text-center
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Drei NoSQL-Modelle
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-3 gap-8 pt-10">
|
|||
|
|
|
|||
|
|
<div class="p-8 rounded-xl bg-red-400/10">
|
|||
|
|
<div class="text-3xl font-bold">Key-Value</div>
|
|||
|
|
<div class="pt-3 opacity-80">Redis</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Alles über Schlüssel</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-8 rounded-xl bg-green-400/10">
|
|||
|
|
<div class="text-3xl font-bold">Dokument</div>
|
|||
|
|
<div class="pt-3 opacity-80">MongoDB</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Alles im Dokument</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-8 rounded-xl bg-blue-400/10">
|
|||
|
|
<div class="text-3xl font-bold">Graph</div>
|
|||
|
|
<div class="pt-3 opacity-80">Neo4j</div>
|
|||
|
|
<div class="pt-2 text-sm opacity-70">Alles über Kanten</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-10 opacity-70">
|
|||
|
|
Wir bilden die gleichen Daten in allen drei ab.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Key-Value mit Redis: alles über Schlüssel
|
|||
|
|
- Dokument mit MongoDB: alles im Dokument
|
|||
|
|
- Graph mit Neo4j: alles über Kanten
|
|||
|
|
- gleiche Daten in allen drei abgebildet
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: two-cols
|
|||
|
|
layoutClass: gap-10
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Key-Value mit Redis
|
|||
|
|
|
|||
|
|
Eine einfache und schnelle Lösung für unstrukturierte Daten.
|
|||
|
|
|
|||
|
|
Keys sind Strings und identifizieren ein Objekt eindeutig.
|
|||
|
|
|
|||
|
|
Aufbau: Name der Entität, Doppelpunkt, ID des Objekts.
|
|||
|
|
|
|||
|
|
::right::
|
|||
|
|
|
|||
|
|
<div class="pt-14">
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
weapon:213
|
|||
|
|
player:1
|
|||
|
|
region:1:items
|
|||
|
|
enemy:1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-6 opacity-80">
|
|||
|
|
|
|||
|
|
Die meisten Entitäten liegen als Hash Map. Listen und Mengen als SET.
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Keys sind Strings und identifizieren ein Objekt eindeutig
|
|||
|
|
- Aufbau: Name der Entität, Doppelpunkt, ID
|
|||
|
|
- meiste Entitäten als Hash Map, Listen und Mengen als SET
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Key-Value: Schlüsselaufbau
|
|||
|
|
|
|||
|
|
<div class="text-sm pt-4">
|
|||
|
|
|
|||
|
|
| Datentyp | Key-Struktur | Attribute |
|
|||
|
|
|----------|--------------|-----------|
|
|||
|
|
| HMAP | `weapon:{id}` | id, item_effect_id, item_type_id, weight, damage |
|
|||
|
|
| HMAP | `item:{id}` | id, name, gear_type, gear_id |
|
|||
|
|
| HMAP | `player:{id}` | id, name, health, stamina, level, region_id |
|
|||
|
|
| SET | `player:{id}:armor` | item_id |
|
|||
|
|
| STRING | `player:{id}:shield` | item_id |
|
|||
|
|
| HMAP | `region:{id}` | id, name |
|
|||
|
|
| SET | `region:{id}:enemies` | enemy_id |
|
|||
|
|
| HMAP | `enemy:{id}` | id, name, health, level, damage |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-4 opacity-70 text-sm">
|
|||
|
|
Über den Key kommen wir direkt an ein Objekt, ohne lange zu suchen.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- jede Entität bekommt einen eigenen Key
|
|||
|
|
- Ausrüstung des Players über Sub-Keys, z.B. player:1:armor
|
|||
|
|
- über den Key direkt ans Objekt, ohne Suchen
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: two-cols
|
|||
|
|
layoutClass: gap-10
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Dokument mit MongoDB
|
|||
|
|
|
|||
|
|
Alles was zusammengehört, liegt gebündelt in einem Dokument.
|
|||
|
|
|
|||
|
|
Jede Entität wird zu einem Dokument in einer eigenen Collection.
|
|||
|
|
|
|||
|
|
Der Player hält von seiner Ausrüstung nur die ids fest, denn Weapon und Co. liegen in eigenen Dokumenten.
|
|||
|
|
|
|||
|
|
::right::
|
|||
|
|
|
|||
|
|
<div class="pt-14">
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
player {
|
|||
|
|
id: 1,
|
|||
|
|
name: "Jonas",
|
|||
|
|
health: 100,
|
|||
|
|
stamina: 100,
|
|||
|
|
level: 1,
|
|||
|
|
region_id: 1,
|
|||
|
|
weapon: [ 12 ],
|
|||
|
|
shield: 30,
|
|||
|
|
armor: [ 41, 42 ],
|
|||
|
|
talisman: [ 7 ]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- alles Zusammengehörige gebündelt in einem Dokument
|
|||
|
|
- jede Entität eigene Collection
|
|||
|
|
- Player hält von der Ausrüstung nur die ids fest
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Dokument: Beispiele
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-3 gap-4 pt-6 text-sm">
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
weapon {
|
|||
|
|
id: 213,
|
|||
|
|
item_type: {
|
|||
|
|
id: 1,
|
|||
|
|
name: "Dolch"
|
|||
|
|
},
|
|||
|
|
item_effect: {
|
|||
|
|
id: 4,
|
|||
|
|
name: "Stärke",
|
|||
|
|
value: 5
|
|||
|
|
},
|
|||
|
|
weight: 2,
|
|||
|
|
damage: 70
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
enemy {
|
|||
|
|
id: 1,
|
|||
|
|
region_id: 1,
|
|||
|
|
name: "Tree_Sentinel",
|
|||
|
|
health: 30000,
|
|||
|
|
level: 20,
|
|||
|
|
damage: 70,
|
|||
|
|
items: [ 5, 10 ]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
region {
|
|||
|
|
id: 1,
|
|||
|
|
name: "Limgrave",
|
|||
|
|
items: [ 12, 19, 248 ],
|
|||
|
|
enemies: [ 1, 245 ]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-6 opacity-70 text-sm">
|
|||
|
|
Weapon bringt item_type und item_effect direkt mit. Player, Item, Region und Enemy zeigen meist nur über ids.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Weapon bringt item_type und item_effect direkt mit
|
|||
|
|
- Enemy und Region verweisen über ids auf ihre Items
|
|||
|
|
- bei uns meist nur ids statt tiefer Verschachtelung
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: two-cols
|
|||
|
|
layoutClass: gap-10
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Graph mit Neo4j
|
|||
|
|
|
|||
|
|
Der Fokus liegt auf den Beziehungen zwischen den Objekten.
|
|||
|
|
|
|||
|
|
Jede Entität wird zu einem Knoten, der seine Werte direkt mitträgt.
|
|||
|
|
|
|||
|
|
::right::
|
|||
|
|
|
|||
|
|
<div class="pt-6 text-sm">
|
|||
|
|
|
|||
|
|
| Knoten | Attribute |
|
|||
|
|
|--------|-----------|
|
|||
|
|
| Player | id, name, health, stamina, level |
|
|||
|
|
| Weapon | id, weight, damage |
|
|||
|
|
| Type | id, name |
|
|||
|
|
| item_effect | id, name, value |
|
|||
|
|
| Item | id, name |
|
|||
|
|
| Region | id, name |
|
|||
|
|
| Enemy | id, name, health, level, damage |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Fokus liegt auf den Beziehungen zwischen Objekten
|
|||
|
|
- jede Entität wird ein Knoten und trägt seine Werte direkt
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Graph: Kanten
|
|||
|
|
|
|||
|
|
<div class="text-sm pt-6">
|
|||
|
|
|
|||
|
|
| Von | Kante | Nach |
|
|||
|
|
|-----|-------|------|
|
|||
|
|
| Player | has_equipped | Weapon, Armor, Shield, Talisman |
|
|||
|
|
| Player | is_in | Region |
|
|||
|
|
| Weapon, Armor, Shield | has | Type |
|
|||
|
|
| Weapon, Armor, Shield, Talisman | has | item_effect |
|
|||
|
|
| Weapon, Armor, Shield, Talisman | is | Item |
|
|||
|
|
| Region | has | Item, Enemy |
|
|||
|
|
| Enemy | drops | Item |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-6 opacity-70 text-sm">
|
|||
|
|
Die Kanten verbinden die Knoten so, wie es schon das ER-Modell vorgibt.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Kanten sind die Beziehungen aus dem ER-Modell
|
|||
|
|
- has_equipped, is_in, has, drops
|
|||
|
|
- Beziehungen lassen sich direkt verfolgen
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Vergleich: Key-Value
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-2 gap-8 pt-10">
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-green-500/10">
|
|||
|
|
<div class="font-bold text-green-500 pb-3">Vorteil</div>
|
|||
|
|
Redis ist extrem schnell. Über die Keys kommen wir direkt an ein Objekt. Genau das brauchen wir für die Live Daten des Players.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-red-500/10">
|
|||
|
|
<div class="font-bold text-red-500 pb-3">Nachteil</div>
|
|||
|
|
Komplexe Abfragen sind schwierig. Alle Weapon mit einem bestimmten item_effect müssen wir in der Anwendung selbst zusammenbauen.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Vorteil: extrem schnell, direkter Zugriff über Key, ideal für Live-Daten
|
|||
|
|
- Nachteil: komplexe Abfragen müssen wir selbst zusammenbauen
|
|||
|
|
- Beispiel: alle Weapon mit bestimmtem item_effect
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Vergleich: Dokument
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-2 gap-8 pt-10">
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-green-500/10">
|
|||
|
|
<div class="font-bold text-green-500 pb-3">Vorteil</div>
|
|||
|
|
Sehr leserlich und einfach zu modellieren. Jedes Dokument ist für sich verständlich und man sieht direkt, welche Daten zusammengehören.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-red-500/10">
|
|||
|
|
<div class="font-bold text-red-500 pb-3">Nachteil</div>
|
|||
|
|
Bei uns wird das meiste über ids referenziert und nur wenig verschachtelt. Wir nutzen die Stärke des Modells kaum.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Vorteil: sehr leserlich und einfach zu modellieren
|
|||
|
|
- Nachteil: bei uns meist ids, kaum verschachtelt
|
|||
|
|
- die eigentliche Stärke nutzen wir kaum
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Vergleich: Graph
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-2 gap-8 pt-10">
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-green-500/10">
|
|||
|
|
<div class="font-bold text-green-500 pb-3">Vorteil</div>
|
|||
|
|
Beziehungen lassen sich sehr leicht abfragen. Welcher Player welche Weapon trägt oder welches Item ein Enemy fallen lässt, ohne Umwege.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-6 rounded-xl bg-red-500/10">
|
|||
|
|
<div class="font-bold text-red-500 pb-3">Nachteil</div>
|
|||
|
|
Neo4j ist für unseren Fall überdimensioniert. Wir schreiben und lesen vor allem schnell, statt ständig tiefe Beziehungen abzufragen.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Vorteil: Beziehungen sehr leicht abfragbar
|
|||
|
|
- Beispiel: welcher Player welche Weapon trägt, welches Item ein Enemy droppt
|
|||
|
|
- Nachteil: für unseren Fall überdimensioniert
|
|||
|
|
- wir brauchen schnelles Schreiben und Lesen, keine tiefen Abfragen
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Gegenüberstellung
|
|||
|
|
|
|||
|
|
<div class="pt-8 text-lg">
|
|||
|
|
|
|||
|
|
| | Key-Value | Dokument | Graph |
|
|||
|
|
|---|:---:|:---:|:---:|
|
|||
|
|
| Schreiben und Lesen | ✅ sehr schnell | 🟡 gut | 🟡 mehr Aufwand |
|
|||
|
|
| Direkter Objektzugriff | ✅ über Key | ✅ über Collection | 🟡 über Knoten |
|
|||
|
|
| Komplexe Abfragen | 🔴 schwierig | 🟡 mittel | ✅ stark |
|
|||
|
|
| Passt zu Live Daten | ✅ ideal | 🟡 ok | 🔴 überdimensioniert |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-8 opacity-70">
|
|||
|
|
Unsere Daten sind flach und ändern sich ständig. Tiefe Beziehungen brauchen wir kaum.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Tabelle fasst die drei Modelle zusammen
|
|||
|
|
- Key-Value vorn bei Tempo und direktem Zugriff
|
|||
|
|
- unsere Daten flach und ständig in Bewegung
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Was uns wichtig ist
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-2 gap-8 pt-6 text-sm">
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
|
|||
|
|
| Kriterium | Muss | Gewicht |
|
|||
|
|
|-----------|:----:|:-------:|
|
|||
|
|
| Hohe Performanz | ja | 5 |
|
|||
|
|
| Keine Lizenzkosten | ja | 5 |
|
|||
|
|
| Daten-Streaming | ja | 3 |
|
|||
|
|
| Niedrige Latenz | ja | 3 |
|
|||
|
|
| Indexing | nein | 2 |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
|
|||
|
|
| | MariaDB | Redis | MongoDB |
|
|||
|
|
|---|:---:|:---:|:---:|
|
|||
|
|
| Performanz | 0 | 2 | 1 |
|
|||
|
|
| Streaming | 0 | 2 | 0 |
|
|||
|
|
| Latenz | 1 | 2 | 0 |
|
|||
|
|
| **Summe** | **11** | **30** | **15** |
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-6 opacity-70 text-sm">
|
|||
|
|
Latenzfrei und performant ist für uns Pflicht. In den Tests gewinnt Redis klar.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Kriterien aus dem Szenario gewichtet
|
|||
|
|
- Performanz und keine Lizenzkosten sind Pflicht
|
|||
|
|
- in den Tests gewinnt Redis klar: 30 vs 11 vs 15
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: center
|
|||
|
|
class: text-center
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Fazit
|
|||
|
|
|
|||
|
|
<div class="text-2xl pt-4">
|
|||
|
|
Wir wählen <span class="text-red-500 font-bold">Key-Value mit Redis</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="grid grid-cols-3 gap-6 pt-10 text-left text-sm">
|
|||
|
|
|
|||
|
|
<div class="p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="font-semibold pb-2">Geschwindigkeit</div>
|
|||
|
|
Daten des Players live schreiben und genauso live zurücklesen.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="font-semibold pb-2">Direkter Zugriff</div>
|
|||
|
|
Über die Keys sofort an ein Objekt, ohne lange Suche.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="p-5 rounded-xl bg-gray-400/10">
|
|||
|
|
<div class="font-semibold pb-2">Passende Größe</div>
|
|||
|
|
Rund 100 Regionen, 500 Gegner, 3.300 Gegenstände. Keine tiefe Verschachtelung nötig.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Wahl fällt auf Key-Value mit Redis
|
|||
|
|
- drei Gründe: Geschwindigkeit, direkter Zugriff, passende Größe
|
|||
|
|
- komplexe Abfragen brauchen wir kaum
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
layout: center
|
|||
|
|
class: text-center
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Danke
|
|||
|
|
|
|||
|
|
<div class="opacity-80 pt-4 text-lg">
|
|||
|
|
Nächste Schritte: Datenbank auf dem Server aufsetzen und Schema umsetzen
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-10 opacity-60">
|
|||
|
|
Fragen?
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="pt-8 opacity-50 text-sm">
|
|||
|
|
Justin Rost · Michelle Reichelt · Yasin Ergün
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!--
|
|||
|
|
- Dank fürs Zuhören
|
|||
|
|
- nächste Schritte: Datenbank auf Server aufsetzen, Schema umsetzen
|
|||
|
|
- offen für Fragen
|
|||
|
|
-->
|