---
title: "Postgres vs. MySQL 2026: Performance, Syntax und die echten Unterschiede"
description: "Worin sich Postgres und MySQL wirklich unterscheiden — Speicherung, MVCC, Verbindungsmodell, SQL-Syntax und Betrieb — plus wo SQLite und MariaDB hingehören und wie man tatsächlich wählt."
author: Aleksei Aleinikov
date: 2026-09-10
lang: de
tags: [postgres-vs-mysql, postgresql, mysql, datenbank-vergleich, sql-performance, mariadb]
canonical: https://www.alekseialeinikov.com/de/blog/topics/data/postgres-vs-mysql-2026-vergleich
source: alekseialeinikov.com
---

# Postgres vs. MySQL 2026: Performance, Syntax und die echten Unterschiede

Die meisten Vergleiche von Postgres und MySQL sind eine Feature-Checkliste von 2015 mit aktualisierten Jahreszahlen. Beide Datenbanken haben inzwischen das meiste nachgeholt, was die jeweils andere früher exklusiv hatte — die Checkliste sagt also fast nichts mehr aus.

Was sich weiterhin unterscheidet, liegt tiefer: wie Zeilen gespeichert werden, wie gleichzeitige Versionen dieser Zeilen verwaltet werden, was eine Verbindung kostet, und was passiert, wenn eine Migration auf halbem Weg scheitert. Diese Unterschiede tauchen in keiner Feature-Tabelle auf — und mit ihnen leben Sie täglich.

![Postgres vs. MySQL 2026: Speicherung, Nebenläufigkeit, Verbindungen und Syntax im Vergleich.](https://www.alekseialeinikov.com/blog/postgres-vs-mysql-2026.webp)

## Die Antwort in 30 Sekunden

- **Komplexe Abfragen, Analytik, JSON, Geodaten, Erweiterungen?** Postgres.
- **Sehr viele einfache Verbindungen, Zugriffe über Schlüssel, Read-Replicas?** MySQL.
- **Team beherrscht bereits eine der beiden?** Diese. Ernsthaft.
- **Grüne Wiese ohne Randbedingungen?** Postgres, weil das Erweiterungs-Ökosystem später mehr Notausgänge bietet.
- **Ein Prozess, kein Netzwerk, kein Betrieb?** Keine von beiden — das ist SQLite.

Alles Weitere ist die Begründung.

## Was sich unter der Haube wirklich unterscheidet

### Speicherung: geclustert gegen Heap

Diese eine Entscheidung erklärt die meisten Performance-Unterschiede.

**MySQL (InnoDB) clustert die Tabelle über den Primärschlüssel.** Die Zeilendaten liegen physisch im Primärschlüsselindex. Ein Zugriff über den Primärschlüssel traversiert einen B-Baum — und Sie halten die Zeile in der Hand.

Der Preis: **Sekundärindizes speichern den Primärschlüssel, keine Zeilenposition**. Ein Zugriff über einen Sekundärindex traversiert also erst diesen Index bis zum Primärschlüssel und dann den Primärschlüsselindex bis zur Zeile. Zwei Traversierungen. Außerdem bläht ein breiter Primärschlüssel jeden Sekundärindex der Tabelle auf.

**Postgres legt Zeilen in einem Heap ab** — einem ungeordneten Haufen von Seiten — und jeder Index, auch der Primärschlüssel, zeigt dort hinein. Jeder Indexzugriff kostet einen zusätzlichen Zugriff auf die Zeile.

Der Vorteil: Alle Indizes sind gleichwertig, ein breiter Primärschlüssel belastet die übrigen nicht, und Postgres kann **Index-Only-Scans** nutzen, wenn die Visibility Map eine Seite als vollständig sichtbar meldet.

**Praktisch heißt das:** MySQL ist hervorragend in „gib mir die Zeile mit dieser ID". Postgres ist ausgewogener, wenn Ihre Zugriffsmuster vielfältig sind.

### MVCC: wo alte Zeilenversionen liegen

Beide liefern Leser, die Schreiber nie blockieren. Sie bezahlen es unterschiedlich.

**Postgres schreibt eine neue Zeilenversion in die Tabelle selbst** und lässt die alte liegen, bis `VACUUM` sie freigibt. Änderungsintensive Tabellen **blähen** dadurch auf, und ob Autovacuum hinterherkommt, ist eine reale Betriebsfrage, keine theoretische.

**MySQL schreibt alte Versionen in Undo-Logs**, die Tabelle bleibt also kompakt. Die Kosten wandern woandershin: Lang laufende Transaktionen lassen das Undo-Log wachsen, und ein Leser auf einem alten Snapshot muss sich durch diese Versionen zurückarbeiten.

Keiner der beiden Wege ist gratis. Postgres zwingt Sie, über Vacuum nachzudenken; MySQL über lange Transaktionen und Undo-Wachstum.

### Verbindungen: Prozess gegen Thread

**Postgres forkt einen Prozess pro Verbindung.** Ein Prozess ist nicht billig. Einige hundert überwiegend untätige Verbindungen kosten echten Speicher, und vor jedem ernsthaften Deployment wollen Sie **PgBouncer** oder einen vergleichbaren Pooler. Serverless-Plattformen, die pro Request eine Verbindung öffnen, verschärfen das.

**MySQL nutzt einen Thread pro Verbindung**, was dramatisch günstiger ist. Tausende Verbindungen sind dort eine gewöhnliche Konfiguration.

Wenn Ihre Architektur viele kurzlebige Verbindungen öffnet und Sie nicht poolen können, entscheidet allein diese Tatsache womöglich Ihre Datenbankwahl.

## Postgres vs. MySQL: Performance

Niemand kann Ihnen ehrlich sagen, welche schneller ist, weil sie bei unterschiedlichen Arbeitsformen schnell sind. Was jede tatsächlich begünstigt:

![Wo Postgres und MySQL gewinnen: geclusterte gegen Heap-Speicherung und ihre unterschiedlichen MVCC-Kosten.](https://www.alekseialeinikov.com/blog/postgres-mysql-architecture-2026.webp)

**MySQL liegt tendenziell vorn bei:**

- Punktzugriffen über den Primärschlüssel — eine Traversierung, Zeile da
- sehr hohen Verbindungszahlen
- einfachem OLTP mit hohem Volumen, wo der Ausführungsplan offensichtlich ist
- Leseskalierung über Replicas, mit ausgereifter Binlog-Replikation

**Postgres liegt tendenziell vorn bei:**

- komplexen Joins, Unterabfragen und Aggregationen — stärkerer Planer
- analytischen Abfragen neben dem transaktionalen Betrieb
- allem mit Teil-, Ausdrucks- oder abdeckenden Indizes
- Schreibmustern, die von `HOT`-Updates ohne Index-Churn profitieren
- JSON, Arrays, Geodaten und Vektoren — dank Erweiterungen

**Ein Wort zu Benchmarks.** Jede Zahl, die Sie lesen — auch jede, die ich veröffentlichen könnte — ist eine Last, ein Schema, ein Hardwareprofil, eine Konfiguration. Tuning verschiebt Ergebnisse stärker als die Wahl der Engine. Wenn Performance wirklich Ihr Entscheidungskriterium ist, messen Sie *Ihre* Abfragen auf *Ihren* Daten. Alles andere ist die Last von jemand anderem.

Wenn Sie nicht wählen, sondern optimieren: Die Techniken aus [SQL-Query-Optimierung](https://www.alekseialeinikov.com/de/blog/topics/data/sql-query-optimierung-2026-schnellere-datenbank-performance) gelten für beide Engines.

## Postgres vs. MySQL: Syntaxunterschiede

Der Abschnitt, der bei einer Portierung zählt. Diese Punkte brechen tatsächlich.

| Thema | Postgres | MySQL |
| --- | --- | --- |
| String-Verkettung | `'a' \|\| 'b'` | `CONCAT('a','b')` |
| Bezeichner quoten | `"meine tabelle"` | `` `meine tabelle` `` |
| Auto-inkrementierender Schlüssel | `GENERATED ALWAYS AS IDENTITY` | `AUTO_INCREMENT` |
| Upsert | `INSERT ... ON CONFLICT DO UPDATE` | `INSERT ... ON DUPLICATE KEY UPDATE` |
| Eingefügte Zeile zurückgeben | `INSERT ... RETURNING *` | nicht unterstützt |
| Boolean | echter `BOOLEAN`-Typ | Alias für `TINYINT(1)` |
| String-Vergleich | standardmäßig case-sensitiv | in üblichen Kollationen case-insensitiv |
| Limit mit Offset | `LIMIT 10 OFFSET 20` | `LIMIT 10 OFFSET 20` oder `LIMIT 20, 10` |
| Aktueller Zeitstempel | `NOW()`, `CURRENT_TIMESTAMP` | `NOW()`, `CURRENT_TIMESTAMP` |
| Arrays | native Array-Typen | nicht unterstützt |
| Regex-Vergleich | `~`, `~*` | `REGEXP`, `RLIKE` |

Drei davon verursachen den meisten Schmerz:

**`RETURNING`.** Postgres gibt Ihnen die soeben geschriebene Zeile in derselben Anweisung zurück. MySQL unterstützt das nicht — Sie fügen ein und selektieren danach, also ein zweiter Roundtrip und ein Wettlauf, wenn Sie nicht aufpassen. MariaDB unterstützt es.

```sql
-- Postgres: eine Anweisung
INSERT INTO users (email) VALUES ('a@b.com')
RETURNING id, created_at;
```

**Groß-/Kleinschreibung.** In Postgres findet `WHERE email = 'Bob@x.com'` ein gespeichertes `bob@x.com` nicht. In MySQL mit üblicher Kollation schon. Portierungen in beide Richtungen ändern das Verhalten stillschweigend, und der Fehler zeigt sich in Produktion als „Login geht manchmal nicht".

**Faltung ungequoteter Bezeichner.** Postgres schreibt ungequotete Bezeichner klein, `CREATE TABLE MyTable` erzeugt also `mytable`. Sobald Sie etwas als `"MyTable"` quoten, müssen Sie es für immer quoten. Der übliche Rat — durchgehend `lower_snake_case`, niemals quoten — lohnt sich in beiden.

## Betrieb: der Unterschied, den niemand erwähnt

**Postgres beherrscht transaktionales DDL.** Sie können Schemaänderungen in eine Transaktion packen und zurückrollen:

```sql
BEGIN;
ALTER TABLE orders ADD COLUMN status text;
-- hier scheitert etwas
ROLLBACK;   -- die Spalte hat nie existiert
```

**MySQL committet bei DDL implizit.** Eine Migration, die bei Schritt vier von sechs scheitert, hinterlässt drei angewandte Änderungen und keinen Rückweg außer einer handgeschriebenen Down-Migration.

Wer häufig Schemaänderungen ausrollt, spürt das im Alltag stärker als jeden Query-Benchmark.

Zwei weitere Betriebsnotizen:

- **Erweiterungen.** Postgres erlaubt PostGIS für Geodaten, pgvector für Embeddings, TimescaleDB für Zeitreihen — in derselben Datenbank, mit denselben Backups und denselben Transaktionen. MySQL hat keinen vergleichbaren Mechanismus. Falls Sie womöglich [eine Vektordatenbank](https://www.alekseialeinikov.com/de/blog/topics/data/brauchst-du-eine-vektordatenbank-postgres-vs-dedizierte-2026) brauchen, zählt das.
- **Replikation.** MySQLs Binlog-Replikation ist alt, gut verstanden und hervorragend mit Werkzeugen versorgt. Postgres bietet physische Streaming-Replikation und logische Replikation; beides funktioniert gut, und die logische Replikation hat in jüngeren Releases deutlich zugelegt.

## Wo SQLite hingehört

SQLite landet oft in diesem Vergleich, meist mit falschem Rahmen.

**SQLite ist keine kleine Serverdatenbank, sondern eine Bibliothek in Ihrem Prozess.** Kein Server, kein Port, keine Benutzerkonten, kein Netzwerk-Roundtrip — ein Funktionsaufruf liest eine Datei.

Das macht es hervorragend für:

- lokalen Anwendungszustand, Caches und Konfiguration
- Testsuites, wo eine Datenbank pro Test Mikrosekunden kostet
- Edge- und eingebettete Deployments
- leseintensive Lasten auf einer einzelnen Maschine

Und ungeeignet, sobald **mehrere Anwendungsserver gleichzeitig schreiben** müssen. SQLite serialisiert Schreiber: einer nach dem anderen.

Die ehrliche Regel: Fasst genau ein Prozess die Daten an, ist SQLite wahrscheinlich richtig — und die einfachste Antwort. Könnten es zwei sein, wollen Sie einen Server.

## MariaDB gegen MySQL

MariaDB entstand nach Oracles Übernahme als MySQL-Fork. Jahre später ist „Drop-in-Ersatz" nicht mehr zutreffend.

Beide haben sich **auseinanderentwickelt**: getrennte Optimizer-Arbeit, unterschiedliche Storage-Engines, und auf jeder Seite Funktionen, die der anderen fehlen. MariaDB hat `RETURNING`, MySQL nicht. Die Versionsnummern korrespondieren überhaupt nicht mehr.

Treiber und einfache Dumps sind weitgehend austauschbar. **Replikation zwischen beiden und neuere Syntax sind es nicht.**

**MariaDB** für Community-Governance und den konkreten Funktionsumfang. **MySQL**, wenn Sie an Oracles Ökosystem, einem darauf aufbauenden verwalteten Angebot oder der exakten Replikationssemantik hängen.

## Welche Versionen betreiben

Stand September 2026:

| Datenbank | Aktuell | Anmerkungen |
| --- | --- | --- |
| PostgreSQL | **18** (18.6) | 19 in der Beta; **14 endet im Nov. 2026** |
| MySQL | **9.7 LTS** (9.7.3) | 8.4 LTS bis 2029; **8.0 endete im Apr. 2026** |
| MariaDB | **12.3 LTS** (12.3.3) | 11.8 und 11.4 LTS weiterhin unterstützt |

Zwei Handlungspunkte: Wer auf **MySQL 8.0** ist, läuft ohne Support — planen Sie den Wechsel auf 8.4 oder 9.7. Wer auf **Postgres 14** ist, hat Zeit bis November.

Postgres liefert jährlich eine Hauptversion mit fünf Jahren Support. MySQL teilt sich in quartalsweise Innovation-Releases und etwa zweijährliche LTS-Releases; betreiben Sie LTS, sofern Sie kein konkretes neues Feature brauchen.

## Die Entscheidungstabelle

| Ihre Situation | Wahl |
| --- | --- |
| Komplexe Abfragen, Reporting neben OLTP | **Postgres** |
| Geodaten, Vektoren, Zeitreihen in einer Datenbank | **Postgres** — Erweiterungen |
| Häufige Schema-Migrationen | **Postgres** — transaktionales DDL |
| Tausende Verbindungen, kein Pooler möglich | **MySQL** |
| Key-Value-artiger Zugriff über Primärschlüssel | **MySQL** — geclusterter Index |
| Starke Leseskalierung über Replicas | **MySQL** — ausgereifte Binlog-Werkzeuge |
| Ein Prozess besitzt die Daten, kein Netzwerk | **SQLite** |
| Community-Governance statt Oracle | **MariaDB** oder Postgres |
| Team beherrscht eine davon tiefgehend | **Diese** |

## Das Fazit

Die Feature-Lücke, die diese Debatte vor einem Jahrzehnt interessant machte, ist weitgehend geschlossen. Geblieben ist Strukturelles: **geclusterte gegen Heap-Speicherung**, **alte Zeilenversionen in der Tabelle gegen Undo-Logs**, **ein Prozess gegen ein Thread pro Verbindung**, und **ob eine gescheiterte Migration zurückrollbar ist**.

Diese vier Unterschiede prägen Ihren Betriebsalltag weit stärker als jede Feature-Checkliste. Entscheiden Sie danach — und danach, welche Ihr Team um drei Uhr nachts debuggen kann.

Und wenn Sie sich anhand eines Benchmarks entscheiden, den Sie nicht selbst gefahren haben, entscheiden Sie anhand der Last von jemand anderem.
