스크립트
00:00:00Es stellt sich also heraus, dass all die Entwickler, die meinten: "Bro, nimm einfach für alles Postgres", noch
00:00:04viel mehr Recht haben mit dem kommenden Release von Postgres 19, das native Unterstützung für Graphenabfragen
00:00:10beinhaltet. Das ist ein wirklich cooles Feature. In dem heutigen Video möchte ich auf alle Hauptfunktionen
00:00:16von Postgres 19 eingehen und mir Graphenabfragen im Speziellen genauer ansehen, weil ich denke, dass
00:00:21sie die Art und Weise, wie wir Abfragen entwerfen und Postgres nutzen, grundlegend verändern kann.
00:00:30Das erste Feature nennt sich "on conflict do select". Wenn man eine Zeile nur dann einfügen möchte, wenn sie
00:00:35nicht bereits existiert, und man in jedem Fall diese Zeile als Ergebnis zurückbekommen will, brauchte man dafür
00:00:40üblicherweise zwei Abfragen: ein Insert und ein Select. Das ist ein wirklich gängiger Workflow. Im Beispiel
00:00:45sagen wir also, wir fügen in die Benutzertabelle E-Mail und Name ein und übergeben diese Werte. Am
00:00:50Ende fügen wir "on conflict for email do nothing returning star" hinzu. "Do nothing" liefert nichts zurück, wenn die Zeile
00:00:56bereits existiert, weshalb man ein Select anhängt. Zusammen ist das jedoch nicht atomar. Mit 19 kann man das
00:01:03in einer einzigen Abfrage erledigen: "Insert into users" mit E-Mail und Name, gefolgt von "on conflict email do select
00:01:11returning star". Wenn man im selben Query modifizieren will, können wir sagen: "Insert into users" und dann erneut
00:01:16die Werte übergeben, gefolgt von "on conflict for email do select for update returning id and name". Da es sich um eine einzige
00:01:23Anweisung handelt, ist sie atomar – sie wird entweder eingefügt oder jedes Mal abgefragt. Da dies ein so
00:01:29häufiger Anwendungsfall ist, wird das wirklich nützlich sein. Als Nächstes kommen Graphen, aber wenn dir das gefällt,
00:01:34dann abonniere doch Better Stack, um bezüglich der neuesten Technologie auf dem Laufenden zu bleiben. Wie bereits gesagt,
00:01:39ist dies meiner Meinung nach das absolute Highlight. Nehmen wir das übliche Schema für einen Shop: Man hat Kunden,
00:01:44Bestellungen und Produkte sowie die beiden Join-Tabellen, die alles miteinander verknüpfen. Man möchte wissen, welches
00:01:50Produkt ein bestimmter Kunde tatsächlich gekauft hat. In SQL ist das eine Kette von Joins über alle fünf Tabellen hinweg.
00:01:56Das ist hier noch recht überschaubar, wird aber bei komplexeren Beziehungen schnell ziemlich unschön. Nun können
00:02:02wir das alles als Graphen abfragen, sodass diese komplexe Join-Syntax durch eine neue Graphen-Syntax ersetzt wird. Insbesondere
00:02:08bei komplexen Joins wird sich hier ein wirklich großer Vorteil zeigen. Wir befinden uns hier in unserem Datenbank-Viewer
00:02:14und sehen all unsere Tabellen: Produkte, Bestellungen, Events, wir haben
00:02:20auch Kunden und dazu die Pivot-Tabellen, um all diese Daten zu verbinden. Wir haben also Positionen von Bestellungen
00:02:25und Kundenbestellungen, und nun lassen Sie uns versuchen, eine Abfrage über all diese Tabellen hinweg auszuführen. Wenn ich zum Beispiel
00:02:30diese Benutzerin hier namens Alice habe, möchte ich herausfinden, was Alice alles bestellt hat. Um
00:02:35dies zu tun, müsste ich eine Reihe verschiedener Join-Abfragen durchlaufen, um all diese Tabellen zu verknüpfen. Ich würde also diesen
00:02:41Query ausführen, der vier separate Join-Anweisungen enthält. Das ist zwar nicht unbedingt schwer
00:02:46zu schreiben, aber sehr unschön. Wenn wir das jedoch ausführen, sehen wir alles, was Alice bestellt hat:
00:02:51die mechanische Tastatur und die ergonomische Maus. Jetzt können wir aber die Graphen-Syntax nutzen, um das massiv
00:02:57zu vereinfachen. Wir ersetzen das alles durch die neue Graphen-Syntax und führen es erneut aus, und man
00:03:03sieht, dass wir dieselben Ergebnisse erhalten. Wenn man das alles untereinander anordnet, wird es leserlicher;
00:03:07man sieht, dass wir einfach von Kunden zu Kundenbestellungen, zu Bestellungen, zu Bestellpositionen und zu Produkten gehen.
00:03:13Man kann im Grunde diesem einfachen Fluss folgen, um sich durch den gesamten Graphen zu bewegen, was meiner Meinung nach viel, viel
00:03:19leichter zu lesen ist. Wenn man auch mehrere Spalten auswählen möchte, können wir das tun: Wir haben oben dieselbe
00:03:23Graphenabfrage, können aber unten Spalten definieren und dann all die Spalten auswählen,
00:03:27die wir anzeigen wollen. Bei der Ausführung erhalten wir die Ergebnisse unten. Nun wird all dies
00:03:32nicht funktionieren, solange wir den Graphen nicht überhaupt erst erstellt haben. Die Abfrage, die ich verwendet habe,
00:03:37um diesen Graphen zu generieren, lautet wie folgt: Wir sagen "create property graph", geben ihm den Namen "my shop" und
00:03:42skizzieren dann die Vertex-Tabellen (Knotentabellen), was Kunden, Bestellungen und Produkte sein werden – das sind also
00:03:47die Dinge, die tatsächlich die Daten enthalten. Dann haben wir die Edge-Tabellen (Kanntentabellen), und das sind die Dinge, die
00:03:52tatsächlich die Verbindungen herstellen, also die Pivot-Tabellen. In unserem Fall wären das Kundenbestellungen und Bestellpositionen,
00:03:57und die Syntax dafür ist super einfach: Wir sagen für Kundenbestellungen, dass die Quelle Kunden und das
00:04:02Ziel Bestellungen ist, und für Bestellpositionen ist die Quelle Bestellungen und das Ziel Produkte. Damit
00:04:08ist Postgres bei jeder Ausführung einer Graphenabfrage nun darüber im Bilde, wie diese Beziehungen definiert sind.
00:04:14Damit dies funktioniert, muss man einen Graphen erstellen, aber das erzeugt keine neuen Tabellen oder Ähnliches;
00:04:19man verweist einfach auf die fünf Tabellen, die man bereits hat: Die drei, die die eigentlichen Daten enthalten, werden zu
00:04:23Vertices, und die zwei Join-Tabellen werden zu Edges. Das Ganze funktioniert viel mehr wie eine View, sodass dein bisheriges Schema
00:04:29völlig unverändert bleibt und du diese Funktionalität einfach obendrauf bekommst. Hier sagen wir also:
00:04:35"create property graph", nennen es "my shop" und beschreiben dann, wie diese Beziehung
00:04:40tatsächlich funktioniert. Hier leisten wir die ganze Arbeit für den Graphen, was bedeutet, dass die Abfragen
00:04:45viel, viel schlanker sein können als die entsprechende Join-Syntax. Ist das nun ein Neo4j-Ersatz? Nun, wenn du eine
00:04:52Graphendatenbank möchtest, weil du Graphenspeicherung und Traversierungsperformance benötigst, dann nein – eine dedizierte Graphen-
00:04:58datenbank ist nach wie vor wahrscheinlich die bessere Wahl. Wenn du dies jedoch möchtest, weil das Schreiben von Joins über 10 Tabellen
00:05:03in SQL mühsam und unschön ist, dann wird es dir definitiv von Nutzen sein und im Vergleich dazu viel angenehmer sein.
00:05:09Das dritte neue Feature ist "repack", und hierbei geht es darum, Speicherplatz auf der Festplatte zurückzugewinnen. Postgres
00:05:15aktualisiert eine Zeile niemals an Ort und Stelle, sondern schreibt eine neue Version und lässt die alte zurück, und Vacuum markiert diesen
00:05:21toten Speicherplatz lediglich als wiederverwendbar, sodass Ihre Festplattennutzung niemals tatsächlich sinkt. Repack schreibt die gesamte
00:05:27Tabelle in eine frische Datei ohne jeglichen verschwendeten Speicherplatz neu, und genau das gibt den Platz an das
00:05:33Betriebssystem zurück. Man konnte das im Grunde schon vorher mit "vacuum full" tun, aber das sperrt die Tabelle für
00:05:38das gesamte Neuschreiben – bei allem, was massiv ist, führt man das also schlichtweg niemals aus. Aus diesem Grund haben Leute
00:05:42Erweiterungen wie pg_repack installiert, aber jetzt bekommen wir das direkt in Postgres integriert. Man verwendet das Schlüsselwort "concurrently" dazu,
00:05:49und dadurch bleibt die Tabelle les- und schreibbar, während repack arbeitet. Eines gilt es hier jedoch zu beachten:
00:05:54Man benötigt genügend freien Festplattenspeicher für eine zweite Kopie der Tabelle und all ihrer Indizes. Man braucht also
00:06:00den zusätzlichen Speicherplatz, um überhaupt mehr Platz freizugeben. Dies ist also kein exakter Ersatz für pg_repack, aber für
00:06:06eine normale Tabelle erledigt es den Job ohne die Erweiterung. Okay, jetzt machen wir eine Schnellfragerunde für
00:06:11die verbleibenden Features des 19er-Releases. Als Erstes sind da Query Hints: Postgres entscheidet selbst, wie deine Abfrage
00:06:17tatsächlich ausgeführt werden soll, und kann seine Meinung im Laufe der Zeit ändern. Eine Abfrage, die ein Jahr lang problemlos lief,
00:06:22wird plötzlich langsam, obwohl sich in deinem Code nichts geändert hat. Ein neues Modul namens "pg_plan_advice" ermöglicht es dir, den Plan zu erfassen,
00:06:28solange er noch schnell ist, und ihn festzulegen, damit er immer so bleibt. JIT ist jetzt standardmäßig deaktiviert: Postgres kompiliert
00:06:36schwere Abfragen zu Maschinencode herunter, hat aber anhand der Kostenschätzung des Planners entschieden, wann es sich lohnt,
00:06:41und laut den Release Notes war diese Kostenberechnung eigentlich unzuverlässig, sodass sie bei Abfragen anspringen konnte, die das
00:06:46eigentlich gar nicht brauchten. Außerdem kann Vacuum nun Ihre Indizes mit mehreren Workern parallel bereinigen, wodurch weniger Zeit
00:06:52für das Bereinigen einer großen Tabelle aufgewendet wird. Man muss das allerdings selbst einschalten. Wenn man eine Spalte hinzufügt,
00:06:58ein Select ausführt und dann dieselbe Spalte auch noch zum Group By hinzufügen muss – es erledigt all das für dich,
00:07:03und das Copy-Schlüsselwort kann nun direkt nach JSON exportieren. Wenn du also bisher CSV gedumpst und es
00:07:09nachträglich konvertiert hast, kannst du damit aufhören. Postgres 19 Beta 2 ist im Juli erschienen, und der finale Release
00:07:15wird um September oder Oktober erwartet. Wenn du also etwas Älteres betreibst, lohnt es sich, die Beta herunterzuladen
00:07:21und dagegen zu testen. Und wenn du mehr über Postgres sehen möchtest, kannst du dir tatsächlich eine
00:07:25Aufschlüsselung von PG Durable ansehen – es bringt dauerhafte Workflows direkt in Postgres. Ich war Warren von
00:07:31Better Stack, vielen Dank fürs Zuschauen und bis zum nächsten Mal.