Zum Inhalt springen

In Iceberg schreiben

Die DuckDB-iceberg-Erweiterung unterstützt das Schreiben in Iceberg-Tabellen, wenn ein Iceberg-Katalog angehängt ist. Das Schreiben in eine Tabelle, die direkt aus dem Speicher mit iceberg_scan gelesen wird, wird nicht unterstützt: Der Katalog ist erforderlich, um die neuen Tabellenmetadaten festzuschreiben.

Unterstützte Operationen

Die iceberg-Erweiterung unterstützt die folgenden Operationen, wenn ein REST Catalog angehängt ist:

  • CREATE/DROP SCHEMA
  • CREATE/DROP TABLE
  • INSERT INTO
  • UPDATE
  • DELETE
  • MERGE INTO
  • ALTER TABLE
  • SELECT

Da diese Operationen unterstützt werden, funktioniert auch Folgendes:

COPY FROM DATABASE duckdb_db TO iceberg_datalake;
-- Or
COPY FROM DATABASE iceberg_datalake TO duckdb_db;

Diese Funktionalität ermöglicht tiefe Kopien zwischen Iceberg- und DuckDB-Speicher.

Tabellen erstellen

Tabellen werden mit der Standard-Syntax von CREATE TABLE erstellt. Iceberg-Tabelleneigenschaften können mit der WITH-Klausel angegeben werden:

CREATE TABLE test_create_table (a INTEGER)
WITH (
'format-version' = '2', -- format version will be elevated to format-version when creating a table
'location' = 's3://path/to/data', -- location will be elevated to location when creating a table
'property1' = 'value1',
'property2' = 'value2'
);

Tabelleneigenschaften können nach dem Erstellen auch eingesehen und geändert werden, siehe Funktionen für Tabelleneigenschaften.

MERGE INTO

Die MERGE INTO-Anweisung ist der empfohlene Weg, um Upserts gegen Iceberg-Tabellen auszudrücken, die keinen Primärschlüssel haben. Sie können eine Änderungsmenge in einer einzigen Anweisung anwenden und pro Zeile entscheiden, ob eingefügt, aktualisiert oder gelöscht werden soll:

MERGE INTO iceberg_catalog.default.people AS target
USING (
FROM (VALUES
(1, 'John', 105_000.0),
(3, 'Sarah', 95_000.0)
) t(id, name, salary)
) AS upserts
ON (upserts.id = target.id)
WHEN MATCHED THEN UPDATE
WHEN NOT MATCHED THEN INSERT;

Sie können auch WHEN MATCHED THEN DELETE verwenden, um in derselben Anweisung eine Löschmenge auszudrücken. Wie bei UPDATE und DELETE verwendet MERGE INTO merge-on-read-Semantik und schreibt positional deletes in die Iceberg-Tabelle.

ALTER TABLE und Schema-Evolution

Die ALTER TABLE-Anweisung wird für Iceberg-Tabellen unterstützt und deckt die gängigsten Schema-Evolution-Operationen ab:

-- Rename the table
ALTER TABLE iceberg_catalog.default.simple_table
RENAME TO renamed_table;
-- Add a column
ALTER TABLE iceberg_catalog.default.renamed_table
ADD COLUMN col3 DOUBLE;
-- Rename a column
ALTER TABLE iceberg_catalog.default.renamed_table
RENAME COLUMN col2 TO name;
-- Drop a column
ALTER TABLE iceberg_catalog.default.renamed_table
DROP COLUMN col3;
-- Set the format-version
ALTER TABLE iceberg_catalog.default.renamed_table
SET ('format-version' = 3);

Jede ALTER TABLE-Anweisung aktualisiert die current-schema-id der Iceberg-Tabelle, und die Änderungen werden für andere Iceberg-fähige Engines sichtbar, sobald diese den Endpunkt LoadTableInformation erneut abfragen. Die Iceberg-Schema-Evolution ist rein metadatenbasiert, es werden also keine Datendateien umgeschrieben.

Partition-Transforms

Zusätzlich zur Identitäts-Partitionierung unterstützt DuckDB-Iceberg das Erstellen, Einfügen und Aktualisieren von Tabellen, die die Partition-Transforms bucket und truncate verwenden (Partition-Transforms).

Der Transform bucket(N, col) hasht den Spaltenwert in N Buckets, was für eine stabile Partitionierung einer Spalte mit hoher Kardinalität nützlich ist. truncate(W, col) gruppiert Zeilen nach den ersten W Zeichen (oder bei numerischen Spalten nach dem auf ein Vielfaches von W abgerundeten Wert), was für präfixbasierte Partitionierung nützlich ist.

CREATE TABLE iceberg_catalog.default.events (
event_id BIGINT,
user_id BIGINT,
country VARCHAR,
payload VARCHAR
)
PARTITIONED BY (bucket(16, user_id), truncate(2, country));

Updates und Deletes gegen mit bucket und truncate partitionierte Tabellen werden ebenfalls unterstützt und verwenden positional deletes unter merge-on-read-Semantik.

Iceberg-V3-Unterstützung

DuckDB-Iceberg unterstützt die folgenden Features der Iceberg-v3-Spezifikation für Lese- und Schreibzugriffe:

  • Datentypen VARIANT und TIMESTAMP_NS
  • Schema-weite Standardwerte für Spalten
  • Binäre Deletion Vectors
  • Row-Lineage-Tracking

Die größte praktische Änderung sind binäre Deletion Vectors. In v2-Tabellen schreibt DuckDB-Iceberg positional deletes als Parquet-Dateien; in v3-Tabellen wird dieselbe Information als deutlich kompakterer binärer Deletion Vector kodiert (Puffin-Datei). DuckDB wählt das passende Format automatisch anhand der format-version der Tabelle. Sie können eine v3-Tabelle erstellen, indem Sie die Tabelleneigenschaft format-version beim Erstellen setzen:

CREATE TABLE iceberg_catalog.default.v3_table
WITH ('format-version' = 3) AS
FROM (VALUES
(1, {'kind': 'click', 'x': 10}::VARIANT, TIMESTAMP_NS '2026-05-20 12:00:00.123456789'),
(2, {'kind': 'view'}::VARIANT, TIMESTAMP_NS '2026-05-20 12:00:00.987654321')
) t(id, payload, event_time);

Warning Die Typen GEOGRAPHY und UNKNOWN werden in DuckDB-Iceberg noch nicht unterstützt; sie sind für DuckDB v2.0.0 geplant.

Einschränkungen für UPDATE und DELETE

Die Operationen UPDATE und DELETE haben die folgenden Einschränkungen:

  • Sie funktionieren nur auf Tabellen, die nicht sortiert sind. Der Versuch, diese Operationen auf sortierten Tabellen auszuführen.
  • DuckDB-Iceberg schreibt nur positional deletes (für v3-Tabellen als binäre Deletion Vectors kodiert). Copy-on-write wird noch nicht unterstützt.
  • DuckDB-Iceberg unterstützt nur merge-on-read-Semantik. Wenn eine Tabelle die Eigenschaften write.update.mode oder write.delete.mode auf etwas anderes als merge-on-read setzt, schlägt die Operation fehl.

Nicht unterstützte Operationen

Die folgenden Operationen werden von der DuckDB-iceberg-Erweiterung noch nicht unterstützt:

  • Die Datentypen GEOGRAPHY und UNKNOWN (geplant für DuckDB v2.0.0)
  • Copy-on-write-Semantik für UPDATE, DELETE und MERGE INTO