Speicherversionen und -format
Kompatibilität
Abwärtskompatibilität
Abwärtskompatibilität bezeichnet die Fähigkeit einer neueren DuckDB-Version, Speicherdateien zu lesen, die von einer älteren DuckDB-Version erzeugt wurden. Version 0.10 ist die erste DuckDB-Version, die Abwärtskompatibilität im Speicherformat unterstützt. DuckDB v0.10 kann Dateien der vorherigen Version – DuckDB v0.9 – lesen und damit arbeiten.
Für künftige DuckDB-Versionen ist unser Ziel, dass jede danach veröffentlichte DuckDB-Version Dateien früherer Versionen lesen kann, beginnend mit diesem Release. Wir wollen das Dateiformat vollständig abwärtskompatibel halten. So können Sie Daten in DuckDB-Dateien aufbewahren und sind sicher, dass Sie die Dateien lesen können, ohne sich um die Schreibversion sorgen oder Dateien zwischen Versionen konvertieren zu müssen.
Vorwärtskompatibilität
Vorwärtskompatibilität bezeichnet die Fähigkeit einer älteren DuckDB-Version, Speicherdateien zu lesen, die von einer neueren DuckDB-Version erzeugt wurden. DuckDB v0.9 ist teilweise vorwärtskompatibel mit DuckDB v0.10. Bestimmte von DuckDB v0.10 erzeugte Dateien können von DuckDB v0.9 gelesen werden.
Vorwärtskompatibilität wird auf Best-Effort-Basis bereitgestellt. Die Stabilität des Speicherformats ist wichtig – dennoch wollen wir das Format künftig noch in vielerlei Hinsicht verbessern und weiterentwickeln. Deshalb kann die Vorwärtskompatibilität gelegentlich (teilweise) gebrochen werden.
Wechseln zwischen Speicherformaten
Wenn Sie DuckDB aktualisieren und eine alte Datenbankdatei öffnen, kann eine Fehlermeldung zu inkompatiblen Speicherformaten erscheinen, die auf diese Seite verweist. Um Ihre Datenbank(en) ins neuere Format zu überführen, benötigen Sie nur die ältere und die neuere DuckDB-Executable.
Öffnen Sie die Datenbankdatei mit der älteren DuckDB und führen Sie die SQL-Anweisung EXPORT DATABASE 'tmp' aus. Damit speichern Sie den gesamten Zustand der aktuell genutzten Datenbank im Ordner tmp.
Der Inhalt des Ordners tmp wird überschrieben; wählen Sie daher einen leeren bzw. noch nicht vorhandenen Ort. Starten Sie anschließend die neuere DuckDB und führen Sie IMPORT DATABASE 'tmp' aus (mit Verweis auf den zuvor befüllten Ordner), um die Datenbank zu laden. Sie kann dann in die Datei geschrieben werden, die Sie DuckDB angegeben haben.
Ein Bash-Skript dafür (Dateinamen und Pfade der ausführbaren Dateien entsprechend anpassen) sieht so aus
/older/duckdb mydata.old.db -c "EXPORT DATABASE 'tmp'"/newer/duckdb mydata.new.db -c "IMPORT DATABASE 'tmp'"Danach bleibt mydata.old.db im alten Format, mydata.new.db enthält dieselben Daten in einem Format, das die neuere DuckDB-Version lesen kann, und der Ordner tmp hält dieselben Daten in einem universellen Format als einzelne Dateien.
Weitere Details zur Syntax finden Sie in der EXPORT-Dokumentation.
Standard-Speicherversion
Standardmäßig erzeugen die DuckDB-Versionen v1.0 bis v1.5 eine DuckDB-Datenbankdatei mit Version 64, entsprechend v1.0.0. Um ein neueres Speicherformat zu nutzen, setzen Sie eine explizite Speicherversion.
Explizite Speicherversionen
DuckDB v1.2.0 hat die Option STORAGE_VERSION eingeführt, mit der sich die Speicherversion explizit festlegen lässt.
So können Sie sich für neuere, vorwärts-inkompatible Funktionen entscheiden:
ATTACH 'file.db' (STORAGE_VERSION 'v1.2.0');Um eine Datenbank mit der neuesten Speicherversion zu initialisieren, verwenden Sie:
ATTACH 'file.db' (STORAGE_VERSION 'latest');Mit dem Kommandozeilen-Client können Sie das Argument -storage-version nutzen:
duckdb -storage-version v1.2.0 my_database.duckdbUm eine Datenbank mit der neuesten Speicherversion anzulegen, verwenden Sie:
duckdb -storage-version latest my_database.duckdbDie Speicherversion gibt die minimale DuckDB-Version an, die die Datenbankdatei lesen können soll. Werden Dateien mit dieser Option geschrieben, können ältere DuckDB-Versionen als die angegebene die resultierenden Dateien nicht öffnen. Die angegebene Version und alle neueren DuckDB-Versionen können sie lesen.
Wenn Sie DuckDB-Datenbanken anhängen, können Sie die Speicherversionen mit folgendem Befehl abfragen:
SELECT database_name, tagsFROM duckdb_databases();Das zeigt die Speicherversionen:
┌───────────────┬───────────────────────────────────┐│ database_name │ tags ││ varchar │ map(varchar, varchar) │├───────────────┼───────────────────────────────────┤│ file1 │ {storage_version=v1.2.0} ││ file2 │ {storage_version=v1.0.0 - v1.1.3} ││ ... │ ... │└───────────────┴───────────────────────────────────┘Das bedeutet, dass file2 von früheren DuckDB-Versionen geöffnet werden kann, während file1 nur mit v1.2.0 (oder künftigen Versionen) kompatibel ist.
Speicherkompatibilität festlegen
Die Konfigurationsoption storage_compatibility_version kann ebenfalls verwendet werden, um die zu nutzende Speicherversion festzulegen. Sie lässt sich auf verschiedene Weise angeben.
Im Python-Client müssen Sie sie beim Verbinden mit einer neuen Datenbank angeben:
duckdb.connect("file.db", config={'storage_compatibility_version': 'latest'})# orduckdb.connect("file.db", config={'storage_compatibility_version': 'v1.4.0'})In der CLI und einigen anderen Clients setzen Sie die Konfigurationsoption so:
SET storage_compatibility_version = 'latest';-- orSET storage_compatibility_version = 'v1.4.0';Im CLI-Client kann die Speicherversion für die gesamte CLI-Sitzung auch über das Kommandozeilenargument -storage-version angegeben werden.
Konvertieren zwischen Speicherversionen
Um vom neuen Format ins alte Format zu konvertieren (für Kompatibilität), verwenden Sie in DuckDB v1.2.0+ die folgende Sequenz:
ATTACH 'file1.db';ATTACH 'converted_file.db' (STORAGE_VERSION 'v1.0.0');COPY FROM DATABASE file1 TO converted_file;Speicher-Header
DuckDB-Dateien beginnen mit einem uint64_t, der eine Prüfsumme für den Hauptheader enthält, gefolgt von vier magischen Bytes (DUCK) und der Speicherversionsnummer in einem uint64_t.
hexdump -n 20 -C mydata.db00000000 01 d0 e2 63 9c 13 39 3e 44 55 43 4b 2b 00 00 00 |...c..9>DUCK+...|00000010 00 00 00 00 |....|00000014Ein einfaches Beispiel zum Auslesen der Speicherversion mit Python folgt.
import struct
pattern = struct.Struct('<8x4sQ')
with open('test/sql/storage_version/storage_version.db', 'rb') as fh: print(pattern.unpack(fh.read(pattern.size)))Tabelle der Speicherversionen
Änderungen in den einzelnen Releases finden Sie im Change Log auf GitHub. Die Commits, die die jeweilige Speicherversion geändert haben, stehen im Commit-Log.
| Speicherversion | DuckDB-Version(en) |
|---|---|
| 68 | v1.5.x |
| 67 | v1.4.x |
| 66 | v1.3.x |
| 65 | v1.2.x |
| 64 | v0.9.x, v0.10.x, v1.0.0, v1.1.x |
| 51 | v0.8.x |
| 43 | v0.7.x |
| 39 | v0.6.x |
| 38 | v0.5.x |
| 33 | v0.3.3, v0.3.4, v0.4.0 |
| 31 | v0.3.2 |
| 27 | v0.3.1 |
| 25 | v0.3.0 |
| 21 | v0.2.9 |
| 18 | v0.2.8 |
| 17 | v0.2.7 |
| 15 | v0.2.6 |
| 13 | v0.2.5 |
| 11 | v0.2.4 |
| 6 | v0.2.3 |
| 4 | v0.2.2 |
| 1 | v0.2.1 und früher |
Komprimierung
DuckDB verwendet leichtgewichtige Komprimierung.
Standardmäßig wird Komprimierung nur auf persistente Datenbanken angewendet und nicht auf In-Memory-Instanzen.
Um Komprimierung für In-Memory-Datenbanken einzuschalten, verwenden Sie ATTACH mit der COMPRESS-Option.
Beachten Sie, dass die verfügbaren Komprimierungsalgorithmen von der verwendeten Speicherversion abhängen. Möglicherweise müssen Sie eine explizite Speicherversion setzen, um alle Algorithmen nutzen zu können.
Komprimierungsalgorithmen
Die von DuckDB unterstützten Komprimierungsalgorithmen umfassen:
- Constant Encoding
- Run-Length Encoding (RLE)
- Bit Packing
- Frame of Reference (FOR)
- Dictionary Encoding
- Fast Static Symbol Table (FSST) – VLDB-2020-Paper
- Adaptive Lossless Floating-Point Compression (ALP) – SIGMOD-2024-Paper
- Chimp – VLDB-2022-Paper
- Patas
- Zstd
Speicherplatzbedarf
Der Speicherplatzbedarf des DuckDB-Formats hängt von mehreren Faktoren ab, darunter Datentyp und Datenverteilung, die verwendeten Komprimierungsverfahren usw. Als grobe Näherung: Das Laden von 100 GB unkomprimierter CSV-Dateien in eine DuckDB-Datenbankdatei benötigt etwa 25 GB Festplattenspeicher, das Laden von 100 GB Parquet-Dateien etwa 120 GB.
Zeilengruppen
Das Speicherformat von DuckDB speichert die Daten in Zeilengruppen (row groups), also horizontalen Partitionen der Daten. Dieses Konzept entspricht den Zeilengruppen von Parquet. Mehrere Funktionen in DuckDB, darunter Parallelität und Komprimierung, basieren auf Zeilengruppen.
Die Zeilengruppengröße kann als Option der ATTACH-Anweisung angegeben werden:
ATTACH '/tmp/somefile.db' AS db (ROW_GROUP_SIZE 16384);Fehlerbehebung
Fehlermeldung beim Öffnen einer inkompatiblen Datenbankdatei
Beim Öffnen einer Datenbankdatei, die von einer anderen DuckDB-Version geschrieben wurde als der, die Sie verwenden, kann die folgende Fehlermeldung auftreten:
Error: unable to open database "...": Serialization Error: Failed to deserialize: ...Die Meldung bedeutet, dass die Datenbankdatei mit einer neueren DuckDB-Version erzeugt wurde und Funktionen nutzt, die mit der zum Lesen verwendeten DuckDB-Version nicht abwärtskompatibel sind.
Es gibt zwei mögliche Workarounds:
- Aktualisieren Sie Ihre DuckDB-Version auf die neueste stabile Version.
- Öffnen Sie die Datenbank mit der neuesten DuckDB-Version, exportieren Sie sie in ein Standardformat (z. B. Parquet) und importieren Sie sie anschließend in eine beliebige DuckDB-Version. Details finden Sie bei den Anweisungen
EXPORT/IMPORT DATABASE.