Zum Inhalt springen

In Iceberg schreiben

Die iceberg-Erweiterung unterstützt das Schreiben in Iceberg-Tabellen, die von einem Iceberg REST Catalog verwaltet werden. Alle Schreiboperationen laufen über den angehängten Katalog und werden als neue Iceberg-Snapshots festgeschrieben.

Das Schreiben erfordert einen angehängten Katalog. Die pfadbasierte iceberg_scan-Schnittstelle, die im Überblick beschrieben ist, ist schreibgeschützt. Um zu schreiben, hängen Sie zuerst einen Iceberg-REST-Katalog an.

Die folgenden Beispiele setzen voraus, dass ein Katalog als my_catalog angehängt wurde.

Schemas und Tabellen erstellen

Iceberg-Namespaces werden als Schemas bereitgestellt. Sie können Schemas und Tabellen mit Standard-SQL erstellen und löschen:

CREATE SCHEMA my_catalog.sales;
USE my_catalog.sales;
CREATE TABLE my_catalog.sales.events (
id INTEGER,
event_name VARCHAR,
event_time TIMESTAMP
);
-- Create a table from a query
CREATE TABLE my_catalog.sales.events_copy AS
FROM my_catalog.sales.events;
DROP TABLE my_catalog.sales.events_copy;

Partitionierung

Tabellen können mit der Klausel PARTITIONED BY unter Verwendung der Iceberg-Partition-Transforms partitioniert werden:

Transform Beschreibung
⟨column⟩{:.language-sql .highlight} Identität – direkt nach dem Spaltenwert partitionieren.
year(⟨column⟩){:.language-sql .highlight}, month(⟨column⟩){:.language-sql .highlight}, day(⟨column⟩){:.language-sql .highlight}, hour(⟨column⟩){:.language-sql .highlight} Nach einer Datums-/Zeitstempel-Komponente partitionieren.
bucket(⟨n⟩, ⟨column⟩){:.language-sql .highlight} Die Spalte in n Buckets hashen.
truncate(⟨n⟩, ⟨column⟩){:.language-sql .highlight} Den Spaltenwert auf die Breite n kürzen.
CREATE TABLE my_catalog.sales.events (
id INTEGER,
event_name VARCHAR,
event_time TIMESTAMP
)
PARTITIONED BY (day(event_time), bucket(16, id));

Die Partitionsspezifikation einer bestehenden Tabelle kann mit ALTER TABLE ... SET PARTITIONED BY geändert werden:

ALTER TABLE my_catalog.sales.events SET PARTITIONED BY (month(event_time));

Die Tabelleneigenschaften write.target-file-size-bytes und write.parquet.row-group-size-bytes werden für partitionierte Tabellen nicht berücksichtigt und lösen einen Fehler aus. Setzen Sie ignore_target_file_size_for_partitioned_tables oder ignore_row_group_size_for_partitioned_tables auf true, um sie stattdessen zu ignorieren.

Tabelleneigenschaften

Iceberg-Tabelleneigenschaften können beim Erstellen mit einer WITH-Klausel gesetzt werden. Die Schlüssel format-version und location werden gesondert erkannt; alle anderen Schlüssel-Wert-Paare werden als Tabelleneigenschaften gespeichert:

CREATE TABLE my_catalog.sales.events (a INTEGER)
WITH (
'format-version' = '2', -- Iceberg format version (2 or 3)
'location' = 's3://my-bucket/events', -- base location for the table's data
'my.custom.property' = 'value'
);

Bestehende Eigenschaften können mit den Property-Funktionen eingesehen und geändert werden:

-- View properties
SELECT * FROM iceberg_table_properties(my_catalog.sales.events);
-- Set properties
CALL set_iceberg_table_properties(
my_catalog.sales.events,
MAP {'write.update.mode': 'merge-on-read', 'write.delete.mode': 'merge-on-read'}
);
-- Remove properties
CALL remove_iceberg_table_properties(my_catalog.sales.events, ['my.custom.property']);

Siehe die Referenz zu Funktionen und Einstellungen für die entsprechenden Schema- (Namespace-) Property-Funktionen.

Daten einfügen

INSERT INTO my_catalog.sales.events
VALUES (1, 'click', TIMESTAMP '2026-06-01 10:00:00');
-- Insert the result of a query
INSERT INTO my_catalog.sales.events
SELECT * FROM source_table;
-- Match columns by name rather than position
INSERT INTO my_catalog.sales.events BY NAME
SELECT event_time, id, event_name FROM source_table;

Aktualisieren und Löschen

UPDATE my_catalog.sales.events SET event_name = 'view' WHERE id = 1;
DELETE FROM my_catalog.sales.events WHERE event_time < TIMESTAMP '2026-01-01';

UPDATE und DELETE werden sowohl auf partitionierten als auch auf nicht partitionierten Tabellen unterstützt. Sie verwenden merge-on-read-Semantik und schreiben positional-delete-Dateien; siehe Einschränkungen.

Daten zusammenführen

MERGE INTO führt ein Upsert gegen eine Quellrelation aus. Der Join-Schlüssel wird mit einer zweiten USING-Klausel angegeben (siehe die MERGE INTO-Anweisung):

MERGE INTO my_catalog.sales.events AS target
USING new_events AS source USING (id)
WHEN MATCHED THEN UPDATE SET event_name = source.event_name
WHEN NOT MATCHED THEN INSERT VALUES (source.id, source.event_name, source.event_time);

Schema weiterentwickeln

Die folgenden ALTER TABLE-Operationen werden unterstützt:

ALTER TABLE my_catalog.sales.events ADD COLUMN source VARCHAR DEFAULT 'web';
ALTER TABLE my_catalog.sales.events DROP COLUMN source;
ALTER TABLE my_catalog.sales.events RENAME COLUMN id TO event_id;
ALTER TABLE my_catalog.sales.events ALTER COLUMN event_id TYPE BIGINT;
ALTER TABLE my_catalog.sales.events RENAME TO event_log;
ALTER TABLE my_catalog.sales.events ALTER COLUMN event_id SET DEFAULT 0;
ALTER TABLE my_catalog.sales.events ALTER COLUMN event_id DROP DEFAULT;

Kopieren zwischen DuckDB und Iceberg

Da der vollständige DDL- und DML-Satz unterstützt wird, kann COPY FROM DATABASE tiefe Kopien zwischen Iceberg- und DuckDB-Speicher in beide Richtungen durchführen:

COPY FROM DATABASE duckdb_db TO my_catalog;
COPY FROM DATABASE my_catalog TO duckdb_db;

Um einen Iceberg-Katalog nach DuckLake zu kopieren, siehe Interoperabilität mit DuckLake.

Einschränkungen

  • UPDATE und DELETE schreiben nur positional deletes; copy-on-write wird nicht unterstützt.
  • UPDATE und DELETE unterstützen nur merge-on-read-Semantik. Wenn eine Tabelle write.update.mode oder write.delete.mode auf etwas anderes als merge-on-read setzt, schlägt die Operation fehl.
  • Die Tabelleneigenschaften write.target-file-size-bytes und write.parquet.row-group-size-bytes werden für partitionierte Tabellen nicht berücksichtigt (siehe Partitionierung).