Ratgeber & Anleitungen

PostgreSQL vs MySQL: Welche Datenbank für Ihr Projekt?

Umfassender Vergleich der beiden beliebtesten relationalen Datenbanken. Features, Performance und Anwendungsfälle im Detail.

Jonas Hottler
24. Januar 2025
14 min Lesezeit
PostgreSQLMySQLDatenbankSQLBackendDatabase
PostgreSQL vs MySQL: Welche Datenbank für Ihr Projekt? - Ratgeber & Anleitungen | Blog

PostgreSQL vs MySQL: Der große Datenbank-Vergleich

PostgreSQL und MySQL sind die beiden dominierenden Open-Source-Datenbanken. Beide sind ausgereift, performant und weit verbreitet. Aber sie haben unterschiedliche Stärken – hier erfahren Sie, welche für Ihr Projekt die richtige Wahl ist.

Die Grundlagen

PostgreSQL

  • Typ: Objektrelationale Datenbank
  • Lizenz: PostgreSQL License (sehr permissiv)
  • Erstveröffentlichung: 1996
  • Philosophie: Feature-Reichheit und Standards-Konformität

MySQL

  • Typ: Relationale Datenbank
  • Lizenz: GPL (+ kommerzielle Lizenz von Oracle)
  • Erstveröffentlichung: 1995
  • Philosophie: Einfachheit und Performance

Feature-Vergleich

FeaturePostgreSQLMySQL
ACID-ComplianceVollständigVollständig (mit InnoDB)
JSON-UnterstützungNativ (JSONB)JSON-Datentyp
Full-Text SearchEingebautEingebaut
ReplikationStreaming + LogicalMaster-Slave, Group
PartitionierungDeclarativeRange, List, Hash
Stored ProceduresPL/pgSQL, Python, PerlSQL/PSM
Materialized ViewsJaNein
Foreign Data WrappersJaNein
Window FunctionsUmfassendAb 8.0
CTEs (WITH)RekursivAb 8.0

Wann PostgreSQL wählen?

1. Komplexe Abfragen

PostgreSQL glänzt bei komplexen analytischen Abfragen:

-- Hierarchische Abfrage mit rekursivem CTE WITH RECURSIVE org_tree AS ( SELECT id, name, manager_id, 1 AS level FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, ot.level + 1 FROM employees e JOIN org_tree ot ON e.manager_id = ot.id ) SELECT * FROM org_tree ORDER BY level, name; -- Window Functions für Ranking SELECT product_name, category, price, RANK() OVER (PARTITION BY category ORDER BY price DESC) as price_rank, AVG(price) OVER (PARTITION BY category) as avg_category_price FROM products;

2. JSON-Daten

PostgreSQL's JSONB ist für semi-strukturierte Daten optimiert:

-- JSONB-Spalte mit Index CREATE TABLE orders ( id SERIAL PRIMARY KEY, customer_id INT, items JSONB, created_at TIMESTAMPTZ DEFAULT NOW() ); -- GIN-Index für schnelle JSON-Suche CREATE INDEX idx_orders_items ON orders USING GIN (items); -- Abfrage auf JSON-Daten SELECT * FROM orders WHERE items @> '[{"product_id": 123}]'; -- JSON aggregieren SELECT customer_id, jsonb_agg(items) as all_items FROM orders GROUP BY customer_id;

3. Geospatial (PostGIS)

Mit PostGIS ist PostgreSQL führend für Geodaten:

-- PostGIS aktivieren CREATE EXTENSION postgis; -- Standorte mit Geometrie CREATE TABLE locations ( id SERIAL PRIMARY KEY, name VARCHAR(100), geom GEOMETRY(Point, 4326) ); -- Alle Standorte im Umkreis von 5km SELECT name, ST_Distance(geom, 'POINT(11.5820 48.1351)'::geography) as distance FROM locations WHERE ST_DWithin(geom, 'POINT(11.5820 48.1351)'::geography, 5000) ORDER BY distance;

4. Datenintegrität

PostgreSQL bietet umfangreiche Constraints:

-- Partielle Unique Constraints CREATE UNIQUE INDEX idx_active_subscription ON subscriptions (user_id) WHERE status = 'active'; -- Check Constraints ALTER TABLE products ADD CONSTRAINT price_positive CHECK (price > 0); -- Exclusion Constraints (keine Überlappung) CREATE TABLE reservations ( room_id INT, during TSTZRANGE, EXCLUDE USING GIST (room_id WITH =, during WITH &&) );

Wann MySQL wählen?

1. Einfache CRUD-Operationen

MySQL ist optimiert für schnelle Lese-/Schreiboperationen:

-- Einfache Abfragen sind sehr schnell SELECT * FROM users WHERE id = 12345; SELECT * FROM products WHERE category_id = 5 LIMIT 20; -- Bulk Inserts INSERT INTO logs (message, level, created_at) VALUES ('Request processed', 'INFO', NOW()), ('Cache hit', 'DEBUG', NOW()), ('Response sent', 'INFO', NOW());

2. Web-Anwendungen (LAMP Stack)

MySQL ist perfekt integriert in:

  • WordPress
  • Drupal
  • Magento
  • Laravel
  • Ruby on Rails
// PHP mit MySQL $pdo = new PDO('mysql:host=localhost;dbname=app', 'user', 'pass'); $stmt = $pdo->prepare('SELECT * FROM posts WHERE author_id = ?'); $stmt->execute([$authorId]); $posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

3. Read-Heavy Workloads

MySQL's Read-Replikation ist einfach einzurichten:

-- Auf dem Master SHOW MASTER STATUS; -- Auf dem Replica CHANGE REPLICATION SOURCE TO SOURCE_HOST='master.example.com', SOURCE_USER='repl_user', SOURCE_PASSWORD='password', SOURCE_LOG_FILE='mysql-bin.000001', SOURCE_LOG_POS=12345; START REPLICA;

4. Managed Services

Nahezu alle Cloud-Provider bieten MySQL:

  • AWS RDS, Aurora MySQL
  • Google Cloud SQL
  • Azure Database for MySQL
  • PlanetScale (Vitess-basiert)

Performance-Vergleich

Benchmarks (typische Ergebnisse)

SzenarioPostgreSQLMySQL
Einfaches SELECT by PK95k QPS110k QPS
Komplexe JOINsSchnellerLangsamer
Bulk INSERT50k/s70k/s
JSON-OperationenSchnellerLangsamer
Concurrent WritesBesserMVCC overhead

Wichtig: Benchmarks variieren stark je nach Konfiguration, Hardware und Anwendungsfall. Testen Sie mit Ihren realen Daten!

Migration zwischen den Systemen

Von MySQL zu PostgreSQL

# Mit pgloader pgloader mysql://user:pass@localhost/dbname \ postgresql://user:pass@localhost/newdb # Oder manuell: # 1. Schema exportieren mysqldump --no-data dbname > schema.sql # 2. Schema konvertieren (Datentypen anpassen) # INT AUTO_INCREMENT → SERIAL # DATETIME → TIMESTAMP # TINYINT(1) → BOOLEAN # TEXT/MEDIUMTEXT/LONGTEXT → TEXT # 3. Daten exportieren/importieren mysqldump --no-create-info --complete-insert dbname > data.sql psql newdb < data.sql

Wichtige Unterschiede beim Migrieren

MySQLPostgreSQL
``` backticks"double quotes"
AUTO_INCREMENTSERIAL / IDENTITY
LIMIT 10, 20LIMIT 20 OFFSET 10
NOW()NOW() / CURRENT_TIMESTAMP
IFNULL()COALESCE()
GROUP_CONCAT()STRING_AGG()
ENUM('a','b')CREATE TYPE ... AS ENUM

ORM-Unterstützung

Beide Datenbanken werden von allen großen ORMs unterstützt:

Node.js (Prisma)

// prisma/schema.prisma datasource db { provider = "postgresql" // oder "mysql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique posts Post[] } // Gleicher Code für beide Datenbanken const users = await prisma.user.findMany({ include: { posts: true } });

Python (SQLAlchemy)

from sqlalchemy import create_engine # PostgreSQL engine = create_engine('postgresql://user:pass@localhost/db') # MySQL engine = create_engine('mysql+pymysql://user:pass@localhost/db') # Rest des Codes bleibt identisch

Hosting-Optionen

PostgreSQL

AnbieterBesonderheit
SupabaseFirebase-Alternative mit Postgres
NeonServerless, Branching
RailwayEinfaches Deployment
AWS RDSEnterprise-ready
RenderKostenloser Tier

MySQL

AnbieterBesonderheit
PlanetScaleServerless, Git-like Branching
AWS AuroraMySQL-kompatibel, hochverfügbar
DigitalOceanEinfache Managed DB
VitessHorizontal Scaling

Fazit und Empfehlung

PostgreSQL wenn:

  • Komplexe Datenmodelle und Abfragen
  • JSON-Daten wichtig sind
  • Geodaten benötigt werden
  • Datenintegrität höchste Priorität hat
  • Sie erweiterte SQL-Features nutzen wollen

MySQL wenn:

  • Einfache CRUD-Anwendungen
  • Bestehende MySQL-Expertise im Team
  • WordPress/Drupal/Magento
  • Maximale Read-Performance gefragt
  • Breite Cloud-Unterstützung wichtig

Unsere Praxis bei Balane Tech

Wir setzen primär PostgreSQL ein für:

  • Neue Projekte
  • Komplexe Business-Logik
  • Anwendungen mit JSON-Daten

MySQL nutzen wir bei:

  • Bestehenden WordPress-Projekten
  • Kundenanforderung für MySQL
  • Einfachen Web-Anwendungen

Beide Datenbanken sind exzellent. Die "richtige" Wahl hängt von Ihren spezifischen Anforderungen ab.

Tags

PostgreSQLMySQLDatenbankSQLBackendDatabase