SQL zu schreiben ist nicht schwer – SQL gut zu schreiben schon.
Beekeeper Studio ist eine kostenlose & quelloffene Datenbank-GUI
Das beste SQL-Abfrage- & Editor-Tool, das ich je benutzt habe. Es bietet alles, was ich zum Verwalten meiner Datenbank brauche. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio ist schnell, intuitiv und einfach zu bedienen. Beekeeper unterstützt jede Menge Datenbanken und läuft hervorragend auf Windows, Mac und Linux.
Abfragen, die in der Entwicklung problemlos laufen, werden in Produktion plötzlich zäh. Ein fehlendes ORDER BY liefert uneinheitliche Ergebnisse, ein schnelles SELECT * bricht bei Schemaänderungen, und Filter, die bei kleinen Datenmengen harmlos wirken, können bei großen Datenmengen alles ausbremsen.
Mit der Zeit erkennst du Muster, die sich bewähren – und solche, die es nicht tun.
Deshalb hier sieben SQL Best Practices vom Team hinter Beekeeper Studio, der modernen, plattformübergreifenden Open-Source-Datenbank-GUI.
🔖 Kurzreferenz: Während du diese Best Practices lernst, halte unser SQL Cheat Sheet griffbereit – zum schnellen Nachschlagen von SELECT, WHERE, JOINs, Aggregaten und weiteren wichtigen SQL-Befehlen.
Beekeeper Studio herunterladen
1. Sei konkret – vermeide SELECT *
Alle Spalten mit SELECT * abzurufen, wirkt schnell und flexibel. Du musst nicht entscheiden, welche Spalten du zurückgibst und welche nicht, und solange du einen Datensatz noch erkundest, funktioniert das gut.
Diese Flexibilität hat ihren Preis. Wenn sich Schemas weiterentwickeln oder Joins zunehmen, kann SELECT * doppelte oder unerwartete Spalten liefern, deine Abfragen verlangsamen und das Debugging erschweren.
Gezielt gewählte Spalten machen die Absicht klar und schützen deinen Code vor unbemerkten Fehlern.
-- Risky
SELECT * FROM user_profiles WHERE user_id = 42;
-- Better
SELECT user_id, display_name, avatar_url
FROM user_profiles
WHERE user_id = 42;
2. Nutze CTEs, um komplexe Logik zu vereinfachen
Verschachtelte Unterabfragen funktionieren, werden aber schnell unlesbar. Es ist schwer zu erkennen, was wo gefiltert wird, und Debugging bedeutet meist, durch Schichten von Klammern hin und her zu scrollen.
Mit Common Table Expressions (WITH-Klauseln) zerlegst du eine Abfrage in benannte Schritte. Jeder Schritt lässt sich einzeln ausführen und testen – so wird die Absicht klarer und Fehler sind leichter aufzuspüren. Denk aber daran, dass manche Datenbanken CTEs materialisieren, daher können Inline-Unterabfragen in engen Schleifen schneller sein.
-- Hard to follow
SELECT customer_id, COUNT(*)
FROM (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
) o
GROUP BY customer_id;
-- Clearer
WITH recent_orders AS (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
)
SELECT customer_id, COUNT(*)
FROM recent_orders
GROUP BY customer_id;
3. Kommentiere deine Absicht, nicht deine Syntax
Inline-Kommentare, die nur wiederholen, was das SQL ohnehin zeigt, bringen wenig. Was du später wirklich vergisst, ist nicht, was die Abfrage tut, sondern warum es sie gibt.
Eine kurze Notiz zu Zweck oder Verwendung macht es leichter, den Code später wieder aufzugreifen oder zu übergeben. Schreib für dein zukünftiges Ich oder die nächste Entwicklerin, die verstehen will, warum diese Abfrage wichtig ist.
-- Find users who signed up but never activated
-- Used in the weekly retention cohort report
SELECT u.id, u.email
FROM users u
LEFT JOIN events e
ON u.id = e.user_id
AND e.name = 'account_activated'
WHERE e.id IS NULL
AND u.created_at > now() - interval '7 days';
4. Mach deine Filter indexfreundlich
Indizes helfen nur, wenn deine Filter sargable sind (kurz für Search ARGument ABLE). In der Praxis heißt das: Die Datenbank kann den Index direkt nutzen, statt jede Zeile zu durchsuchen.
Wenn du eine Spalte in eine Funktion packst – etwa LOWER(email) oder DATE(created_at) –, kann der Optimizer den Index nicht nutzen. Selbst Typumwandlungen können denselben Effekt haben. Die Abfrage funktioniert weiterhin, wird aber mit wachsenden Daten langsamer.
-- Not sargable: disables index
WHERE LOWER(email) = 'test@example.com';
-- Sargable: uses existing index
WHERE email = 'test@example.com';
Damit Filter effizient bleiben, schreib sie passend dazu, wie die Daten gespeichert sind. Brauchst du einen Vergleich ohne Groß-/Kleinschreibung, speichere Werte in einem einheitlichen Format oder lege einen funktionalen Index an. Bei Datumswerten filterst du besser nach Bereich, statt die Spalte umzuwandeln – das ist klarer und der Index bleibt im Spiel.
-- Not sargable
WHERE DATE(created_at) = '2025-08-04';
-- Sargable
WHERE created_at >= '2025-08-04'
AND created_at < '2025-08-05';
5. Filtere vor dem Join
Es ist verlockend, erst alles zu joinen und später zu filtern – besonders beim Erkunden oder Prototyping. Aber jeder Join vervielfacht die Zeilen, und jede unnötige Zeile macht deine Abfrage langsamer und für den Optimizer schwerer zu planen.
Grenze stattdessen jede Tabelle ein, bevor du sie kombinierst. So joint die Datenbank nur die Daten, die wirklich zählen – das spart Speicher, verbessert die Cache-Effizienz und hält den Ausführungsplan vorhersehbar.
-- Joins every user, even inactive ones
SELECT e.*
FROM users u
JOIN events e ON e.user_id = u.id;
-- Filter first: only active, recently seen users
WITH active_users AS (
SELECT id
FROM users
WHERE active = true
AND last_seen > now() - interval '90 days'
)
SELECT e.*
FROM active_users u
JOIN events e ON e.user_id = u.id;
6. Bevorzuge EXISTS statt IN bei Beziehungsprüfungen
Wenn du prüfst, ob verknüpfte Zeilen existieren, erledigt IN den Job – bis es das nicht mehr tut. Es baut eine vollständige Werteliste auf, vergleicht jeden Wert und behandelt NULL-Werte so, dass gültige Treffer verborgen bleiben können.
EXISTS funktioniert anders. Es liefert true, sobald es einen Treffer findet, und wird von NULL-Werten in der Unterabfrage nicht beeinflusst. Das Ergebnis ist schneller und zuverlässiger, besonders bei großen Datenmengen.
-- Works, but can be slower and NULL-prone
SELECT *
FROM users
WHERE id IN (SELECT user_id FROM orders);
-- Clear and efficient: stops at first match
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
7. Gib immer ORDER BY an
SQL garantiert keine Zeilenreihenfolge, wenn du nicht danach fragst.
Ohne ORDER BY darf die Datenbank Zeilen in beliebiger Reihenfolge zurückgeben – und die kann sich zwischen Ausführungen, Umgebungen oder sogar kleinen Updates ändern.
In der Entwicklung mag das stabil aussehen, aber sobald sich Indizes, Ausführungspläne oder Datenmengen ändern, bekommst du unvorhersehbare Paginierung oder inkonsistente API-Ergebnisse.
-- Looks fine until it isn't
SELECT id, name
FROM users
WHERE active = true
LIMIT 10;
-- Predictable and reproducible
SELECT id, name
FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10;
Alles zusammengefasst
Die besten Abfragen sind die, die du auch ein Jahr später noch verstehst. Sie haben eine klare Absicht, vorhersehbares Verhalten und keine versteckten Überraschungen.
Genau darum geht es bei diesen Gewohnheiten. Wir nutzen sie jeden Tag bei Beekeeper Studio, um Abfragen lesbar, konsistent und schnell zu halten – in jeder Datenbank, mit der wir arbeiten.
Du kannst dir eine kostenlose PDF-Version dieses Guides holen, um sie griffbereit zu haben oder mit deinem Team zu teilen:
7 SQL Habits for Busy Developers herunterladen
Mit Beekeeper Studio setzt du diese Gewohnheiten im Alltag um – mit einem modernen, plattformübergreifenden Open-Source-SQL-Editor, der dich im Flow hält.
- Über 20 unterstützte Datenbanken: Postgres, MySQL, SQLite, SQL Server, MongoDB, Redis und mehr.
- Schneller, reaktionsfreudiger Editor: Schemabewusste Autovervollständigung, Abfragen in Tabs und Syntaxhervorhebung.
- Visuelle Datentools: Tabellen durchsuchen, Zeilen bearbeiten und JSON untersuchen, ohne den Kontext zu verlieren.
- KI-Assistent (Privatsphäre zuerst): Das fehlende KI-Coding-Tool für deine Datenbank – schemabewusst, funktioniert mit dem LLM deiner Wahl und hilft dir, Abfragen schneller zu erkunden und zu verfeinern.
Beekeeper Studio herunterladen