📄Das Dateiformat
Eine SQLite-Datenbank ist genau eine Datei – und ihr Format ist offen dokumentiert, stabil seit 2004 und wird laut sqlite.org mindestens bis 2050 unterstützt. Alle Angaben auf dieser Seite folgen sqlite.org/fileformat.html; die Beispielwerte stammen aus der echten, beim Build erzeugten Beispiel-Datenbank.
🧱Die Datei besteht aus Seiten
🪪Der 100-Byte-Datenbankkopf
🌳B-Baum-Seiten
Aufbau einer Seite
Offset 0 Seitenende
┌───────────┬─────────────┬───────────────┬──────────────────┬──────────┐
│ Dateikopf │ Seitenkopf │ Zellzeiger- │ unbenutzt │ Zellen │
│ (100 B, │ 8 B Blatt / │ Array: je 2 B │ ◄── wächst ──│ ◄── wach-│
│ nur S. 1) │ 12 B innen │ ─► wächst ─► │ │ sen │
└───────────┴─────────────┴───────────────┴──────────────────┴──────────┘
▲ ▲
Ende Zeiger-Array Kopf-Offset 5:
Beginn Zellinhalt
• Zellzeiger sind nach Schlüssel sortiert, die Zellen selbst nicht.
• Gelöschte Zellen werden zu Freeblocks (Kette ab Kopf-Offset 1);
Lücken unter 4 Bytes zählen als „fragmentierte Bytes“ (Offset 7).Seitenkopf
| Offset | Größe | Inhalt |
|---|---|---|
| 0 | 1 | Seitentyp (0x02, 0x05, 0x0a, 0x0d) |
| 1 | 2 | Beginn des ersten Freeblocks (0 = keiner) |
| 3 | 2 | Anzahl Zellen auf der Seite |
| 5 | 2 | Beginn des Zellinhaltsbereichs (0 bedeutet 65 536) |
| 7 | 1 | Anzahl fragmentierter freier Bytes |
| 8 | 4 | rechtester Kindzeiger – nur bei inneren Seiten |
| Typ-Byte | dez. | Seitentyp | Kopf | Aufbau einer Zelle |
|---|---|---|---|---|
| 0x02 | 2 | Index – innere Seite | 12 B | linker Kindzeiger (4 B) · Payload-Größe (Varint) · Schlüssel-Payload · ggf. Overflow-Zeiger |
| 0x05 | 5 | Tabelle – innere Seite | 12 B | linker Kindzeiger (4 B) · Rowid-Schlüssel (Varint) – keine Daten! |
| 0x0a | 10 | Index – Blattseite | 8 B | Payload-Größe (Varint) · Schlüssel-Payload · ggf. Overflow-Zeiger |
| 0x0d | 13 | Tabelle – Blattseite | 8 B | Payload-Größe (Varint) · Rowid (Varint) · Record · ggf. Overflow-Zeiger |
🔢Varints
Zahl → Varint
2 Bytes. Rotes Bit = „es folgt ein Byte“, die übrigen 7 Bit sind Nutzdaten (höherwertige zuerst).
Hex → Zahl
144115188075855872 (9 Bytes gelesen)
| Bytes | Wertebereich |
|---|---|
| 1 | 0 … 2^7 − 1 = 127 |
| 2 | 0 … 2^14 − 1 = 16.383 |
| 3 | 0 … 2^21 − 1 = 2.097.151 |
| 4 | 0 … 2^28 − 1 = 268.435.455 |
| 5 | 0 … 2^35 − 1 = 34.359.738.367 |
| 6 | 0 … 2^42 − 1 = 4.398.046.511.103 |
| 7 | 0 … 2^49 − 1 = 562.949.953.421.311 |
| 8 | 0 … 2^56 − 1 = 72.057.594.037.927.935 |
| 9 | alle 64-Bit-Werte, auch negative |
🧾Das Record-Format
Unterstrichen = Record-Header (8 Bytes), danach der Body. Gleiche Farbe = Serial Type und Inhalt derselben Spalte.
| Spalte | Wert | Serial Type | Bedeutung | Inhalt |
|---|---|---|---|---|
| 0 | NULL | 0 | NULL | 0 B |
| 1 | 'Anna Linde' | 33 | TEXT, 10 Bytes | 10 B |
| 2 | 'Seedorf' | 27 | TEXT, 7 Bytes | 7 B |
| 3 | 1 | 9 | Ganzzahl 1 (ohne Inhalt) | 0 B |
| 4 | 30000 | 2 | Ganzzahl 16 Bit | 2 B |
| 5 | 3.25 | 7 | Gleitkomma 64 Bit (IEEE 754) | 8 B |
| 6 | x'cafe' | 16 | BLOB, 2 Bytes | 2 B |
Tipp: In einer Tabelle mit INTEGER PRIMARY KEY steht an dieser Stelle NULL (Serial Type 0) – der Wert ist die Rowid und steht schon im Zellkopf. Ganzzahlen 0 und 1 kosten dank Serial Type 8/9 gar kein Byte im Body.
| Serial Type | Inhaltslänge (Bytes) | Bedeutung |
|---|---|---|
| 0 | 0 | NULL |
| 1 | 1 | Ganzzahl, 8 Bit, Zweierkomplement |
| 2 | 2 | Ganzzahl, 16 Bit, Big-Endian |
| 3 | 3 | Ganzzahl, 24 Bit |
| 4 | 4 | Ganzzahl, 32 Bit |
| 5 | 6 | Ganzzahl, 48 Bit |
| 6 | 8 | Ganzzahl, 64 Bit |
| 7 | 8 | Gleitkommazahl IEEE 754, 64 Bit, Big-Endian |
| 8 | 0 | die Ganzzahl 0 (ab Schemaformat 4) |
| 9 | 0 | die Ganzzahl 1 (ab Schemaformat 4) |
| 10, 11 | – | reserviert für interne Zwecke |
| N ≥ 12, gerade | (N − 12) / 2 | BLOB |
| N ≥ 13, ungerade | (N − 13) / 2 | TEXT in der Kodierung der Datenbank (ohne Nullbyte) |
Beispiel: TEXT 'Seedorf' hat 7 Bytes → Serial Type 7·2+13 = 27 = 0x1b. REAL-Spalten speichern ganzzahlige Werte intern platzsparend als Ganzzahl; beim Lesen macht der Opcode RealAffinity wieder eine Gleitkommazahl daraus.
🧵Overflow-Seiten
P > X: 960 Bytes bleiben in der Zelle (K ≤ X → K), 2.040 Bytes verteilen sich auf 2 Overflow-Seite(n) mit je 1020 Nutzbytes (4 Bytes je Seite für den Zeiger auf die nächste). Die Wahl von K sorgt dafür, dass die letzte Overflow-Seite möglichst voll ist.
In der Beispiel-DB ist der Record der Notiz „Lang“ 2 861 Bytes groß. Bei U = 1024 gilt X = 989, M = 103 und K = 103 + (2 758 mod 1020) = 821 ≤ X: 821 Bytes bleiben in der Zelle, die restlichen 2 040 Bytes füllen genau zwei Overflow-Seiten à 1020 Nutzbytes.