Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 6 Min.

SQLite: Wenn weniger mehr ist

Für Entwicklerteams, die jeden Tag mit der Komplexität von Kubernetes, Cloud-Datenbanken und Terraform-Skripten ringen, liegt der eigentliche Gewinn von SQLite in der architektonischen Vereinfachung.
© EMGenie

Neues .NET-Projekt, neues Backend, und als Erstes wird der Datenbankserver aufgesetzt. SQL Server in Docker, PostgreSQL in der Cloud, Connection Strings, Migrations, Backup-Skripte: Für viele Entwickler ist das Routine, und niemand hinterfragt, ob dieser Aufwand überhaupt nötig ist. Dabei gibt es eine Datenbank, die auf jedem Smartphone, in jedem Browser und in Millionen von IoT-Geräten läuft und die für überraschend viele Anwendungsfälle mehr als ausreichend ist: SQLite.

Mehr als eine Spielzeug-Datenbank

SQLite ist die meistverbreitete Datenbank der Welt. Nicht weil sie die leistungsfähigste wäre, sondern weil sie überall läuft: in Android und iOS, in Chrome und Firefox, in Skype und iTunes, in jedem PHP-Stack und in zahllosen Embedded-Systemen. D. Richard Hipp hat sie im Jahr 2000 als Bibliothek entworfen, die direkt in die Anwendung eingebettet wird – kein Server, kein Netzwerk, keine Konfiguration. Die gesamte Datenbank ist eine einzige Datei.

Für .NET-Entwickler, die SQL Server oder PostgreSQL gewohnt sind, klingt das nach einem Downgrade. Kein Connection Pooling, keine Netzwerkfähigkeit, keine Multi-User-Architektur, wo soll da der Vorteil sein? Die Antwort liegt in der Reduktion: Kein Docker-Container, der gewartet werden muss. Keine Credentials, die rotiert werden müssen. Kein Backup-Skript, das auf einen externen Server zeigt. SQLite ist Zero-Config im wörtlichsten Sinne, und genau das ist für viele Szenarien kein Bug, sondern ein Feature.

Dazu kommt ein Aspekt, der gerade für sicherheitskritische Anwendungen relevant ist: SQLite hat eine der umfangreichsten Testsuiten in der gesamten Softwareindustrie. Über 100 Prozent Branch-Coverage, Millionen von Testfällen, und das Projekt hat um den Faktor 600 mehr Testcode als Produktivcode. Diese Qualität zeigt sich in der Praxis: Datenkorruption durch SQLite selbst ist praktisch ausgeschlossen, solange das Dateisystem korrekt arbeitet.

Performance: Die Zahlen können beeindrucken

Das verbreitete Vorurteil lautet: SQLite ist langsam. Die Realität sieht anders aus. Für Leseoperationen, und das ist der überwiegende Anteil in den meisten Webanwendungen, ist SQLite oft schneller als PostgreSQL oder SQL Server, schlicht weil der Netzwerk-Overhead entfällt. Ein SELECT auf eine indizierte Spalte, der bei einer Server-Datenbank über TCP/IP geht, dauert bei SQLite nur einen Funktionsaufruf im selben Prozess. Einzelne Benchmarks zeigen, dass SQLite im WAL-Modus über 400.000 Lese-Operationen pro Sekunde schafft, auf handelsüblicher Hardware. Diese Zahlen beziehen sich auf ein Go-Tool zum Benchmarking von SQLite-Datenbanken. Hier wurde ein MacBook von 2017 genutzt.,

Der Schlüssel dazu ist der WAL-Modus (Write-Ahead Logging). Im Standard-Journal-Modus sperrt SQLite die gesamte Datei bei Schreibzugriffen. Im WAL-Modus können Leser und ein Schreiber gleichzeitig arbeiten, ein enormer Unterschied für Webanwendungen, bei denen Lesen den Großteil ausmacht. Die Konfiguration ist denkbar einfach:

 

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA cache_size = -20000; -- 20 MB Cache
PRAGMA busy_timeout = 5000;
PRAGMA mmap_size = 268435456; -- 256 MB

 

SQLite transformiert von einer simplen Embedded-Datenbank in ein System, das für die meisten Read-Heavy-Workloads mit Server-Datenbanken mithalten kann. WAL aktiviert paralleles Lesen, synchronous=NORMAL bietet einen guten Kompromiss zwischen Sicherheit und Geschwindigkeit, der vergrößerte Cache hält häufig genutzte Pages im Speicher, busy_timeout verhindert sofortige Fehler bei konkurrierenden Schreibzugriffen, und Memory-Mapped I/O beschleunigt den Dateizugriff zusätzlich.

Bei Schreiboperationen sieht die Rechnung etwas anders aus. SQLite serialisiert Schreibzugriffe: nur ein Writer gleichzeitig. Das klingt nach einer harten Limitierung, relativiert sich aber in der Praxis. Mit WAL-Modus und Batching erreicht SQLite mehrere Tausend Schreibtransaktionen pro Sekunde. Für die meisten API-Backends, Microservices oder interne Tools ist das mehr als genug.

Ein häufiger Einwand ist die Backup-Frage: Wie sichert man eine Datei, in die gerade geschrieben wird? Die Antwort ist der .backup-Befehl, der eine konsistente Kopie erstellt, während die Datenbank aktiv ist. Wem das nicht reicht, der kann mit Litestream die WAL-Änderungen kontinuierlich auf S3 oder Azure Blob Storage streamen: Point-in-Time Recovery für eine Embedded-Datenbank, die eigentlich gar keinen Server hat.

Wann SQLite die richtige Wahl ist

Die Faustregel ist einfacher als gedacht: Wenn eine Anwendung auf einem einzelnen Server läuft und der Schreibdurchsatz unter einigen Tausend Transaktionen pro Sekunde bleibt, ist SQLite oft die bessere Wahl. Konkrete Szenarien, in denen wir SQLite erfolgreich einsetzen: API-Backends für mobile Apps mit moderatem Traffic, Microservices mit eigener Datenhaltung, bei denen jede Instanz ihre eigene Datenbank mitbringt, Desktop- und Electron-Anwendungen, bei denen die Datenbank lokal läuft, und Prototypen, die später ohne Migration in Produktion gehen können.

Ein besonders interessanter Anwendungsfall ist Edge Computing. Wenn die Anwendung auf einem Raspberry Pi, einem IoT-Gateway oder einem Edge-Server läuft, ist ein separater Datenbankserver schlicht überdimensioniert. SQLite bringt alles mit, was man braucht, in einer Bibliothek von unter 1 MB. Und für Deployment-Szenarien, in denen die Datenbank als Teil des Anwendungspakets ausgeliefert wird, etwa bei MAUI-Apps oder Blazor Hybrid, gibt es kaum eine bessere Alternative.

Wo die Grenzen liegen und wo nicht

Natürlich hat SQLite echte Grenzen. Die offensichtlichste: kein Netzwerkzugriff. Die Datenbank läuft immer im selben Prozess wie die Anwendung. Mehrere Server können nicht auf dieselbe SQLite-Datei zugreifen, zumindest nicht mit Standard-SQLite. Außerdem gibt es keine eingebaute Benutzer-Authentifizierung und keine feingranulare Zugriffskontrolle wie GRANT und REVOKE in SQL Server.

Aber viele vermeintliche Grenzen existieren längst nicht mehr. SQLite unterstützt seit Jahren Common Table Expressions, Window Functions, UPSERT, JSON-Funktionen und Full-Text-Search. Wer vor drei Jahren das letzte Mal hingeschaut hat, wird überrascht sein, wie viel sich getan hat. Ein Beispiel für die JSON-Unterstützung:

 

SELECT
  json_extract(data, ‘$.name’) AS name,
  json_extract(data, ‘$.address.city’) AS city
FROM customers
WHERE json_extract(data, ‘$.active’) = 1;

 

Wer mit OPENJSON in SQL Server oder jsonb in PostgreSQL arbeitet, wird die Syntax wiedererkennen. Die JSON-Funktionen von SQLite sind vollständig. Inklusive json_each() für das Iterieren über Arrays und json_patch() für Merge-Operationen. In Kombination mit Generated Columns lassen sich JSON-Felder sogar indizieren, was die Query-Performance für häufig abgefragte Pfade auf das Niveau klassischer Spalten hebt.

Weniger Infrastruktur, mehr Fokus

Der eigentliche Gewinn von SQLite liegt nicht in der Performance, die ist ein willkommener Bonus. Der Gewinn liegt in der architektonischen Vereinfachung. Kein Datenbankserver bedeutet: ein Deployment-Artefakt weniger, ein Sicherheitsrisiko weniger, ein Monitoring-Target weniger. Backups sind ein simples File-Copy oder ein .backup-Befehl. Die Datenbank kann als Teil der CI/CD-Pipeline mit ausgeliefert werden, vorbefüllt mit Referenzdaten oder komplett leer als Schema-Template.

Für Entwicklerteams, die jeden Tag mit der Komplexität von Kubernetes, Cloud-Datenbanken und Terraform-Skripten ringen, ist SQLite eine Erinnerung daran, dass Softwareentwicklung auch einfach sein kann. Nicht jede Anwendung braucht eine verteilte Datenbank. Nicht jedes Projekt braucht einen Connection Pool. Manchmal ist eine Datei genug, eine gut optimierte, kampferprobte Datei, die seit über zwei Jahrzehnten in Milliarden von Geräten ihren Dienst tut.

Im nächsten Teil dieser Serie schauen wir uns an, wie nahtlos sich SQLite in die .NET-Welt einfügt, von Microsoft.Data.Sqlite über Entity Framework Core bis hin zu Dapper. Spoiler: Die Integration ist einfacher als bei jeder anderen Datenbank.

Neueste Beiträge

SignalRC und Ping - Der DDC-Truck, Teil 10
Wie schnell ist die Verbindung zwischen Browser und Fahrzeug eigentlich?
9 Minuten
26. Mär 2026
SignalRC mit ReactFlow – alles im Fluss - Der DDC-Truck, Teil 9
ReactFlow verwandelt ein abstraktes Signalverarbeitungsproblem in etwas, das man buchstäblich sehen und anfassen kann. Dabei ist die Signalverarbeitungskette vollständig datengetrieben.
13 Minuten
19. Mär 2026
Mit Entitäten strukturierte Informationen extrahieren - Low Code/No Code und KI mit Copilot Studio, Teil 2
Entitäten in Copilot Studio strukturieren Benutzereingaben als typisierte, wiederverwendbare Informationen. Sie erkennen und extrahieren aus unstrukturierter Sprache klar definierte Daten für Dialoglogik und zur Übergabe an Aktionen (Power Automate, Konnektoren/Plug-ins).
7 Minuten
23. Mär 2026

Das könnte Dich auch interessieren

Pflichterfüllung - Strukturierte elektronische Rechnungen (E-Invoicing) mit .NET selbst implementiert
.NET-Entwickler können die ab 2025 im B2B-Markt einsetzende Pflicht zur strukturierten elektronischen Rechnungsstellung und -annahme mit Open-Source-Lösungen erfüllen.
17 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige