PostgreSQL-Erweiterung
Die postgres-Erweiterung ermöglicht DuckDB, Daten direkt aus einer laufenden PostgreSQL-Datenbankinstanz zu lesen und zu schreiben. Die Daten können direkt aus der zugrunde liegenden PostgreSQL-Datenbank abgefragt werden. Daten können aus PostgreSQL-Tabellen in DuckDB-Tabellen geladen werden oder umgekehrt. Siehe die offizielle Ankündigung für Implementierungsdetails und Hintergrund.
Installation und Laden
Die postgres-Erweiterung wird beim ersten Gebrauch transparent aus dem offiziellen Erweiterungs-Repository automatisch geladen.
Wenn Sie sie manuell installieren und laden möchten, führen Sie aus:
INSTALL postgres;LOAD postgres;Verbindung herstellen
Damit eine PostgreSQL-Datenbank für DuckDB zugänglich ist, verwenden Sie den Befehl ATTACH mit dem Typ postgres oder postgres_scanner.
Um sich im Lese-Schreib-Modus mit dem Schema public der auf localhost laufenden PostgreSQL-Instanz zu verbinden, führen Sie aus:
ATTACH '' AS postgres_db (TYPE postgres);Um sich mit der PostgreSQL-Instanz mit den angegebenen Parametern im Nur-Lesen-Modus zu verbinden, führen Sie aus:
ATTACH 'dbname=postgres user=postgres host=127.0.0.1' AS db (TYPE postgres, READ_ONLY);Standardmäßig werden alle Schemas angehängt. Bei großen Instanzen kann es sinnvoll sein, nur ein bestimmtes Schema anzuhängen. Das kann mit dem Befehl SCHEMA erreicht werden.
ATTACH 'dbname=postgres user=postgres host=127.0.0.1' AS db (TYPE postgres, SCHEMA 'public');Deprecated Die alte Funktion
postgres_attachist veraltet. Es wird empfohlen, auf die neueATTACH-Syntax umzusteigen.
Konfiguration
Der Befehl ATTACH nimmt als Eingabe entweder eine libpq-Verbindungszeichenkette
oder eine PostgreSQL-URI.
Nachfolgend einige Beispiel-Verbindungszeichenketten und häufig verwendete Parameter. Eine vollständige Liste verfügbarer Parameter finden Sie in der PostgreSQL-Dokumentation.
dbname=postgresscannerhost=localhost port=5432 dbname=mydb connect_timeout=10| Name | Beschreibung | Standard |
|---|---|---|
dbname |
Datenbankname | [user] |
host |
Name des Hosts, mit dem verbunden werden soll | localhost |
hostaddr |
Host-IP-Adresse | localhost |
passfile |
Name der Datei, in der Passwörter gespeichert sind | ~/.pgpass |
password |
PostgreSQL-Passwort | (empty) |
port |
Portnummer | 5432 |
user |
PostgreSQL-Benutzername | current user |
Ein Beispiel für eine URI ist postgresql://username@hostname/dbname.
Konfiguration über Secrets
PostgreSQL-Verbindungsinformationen können auch über Secrets angegeben werden, Details siehe auf der entsprechenden Seite.
Konfiguration über Umgebungsvariablen
PostgreSQL-Verbindungsinformationen können auch über Umgebungsvariablen angegeben werden. Das kann in einer Produktionsumgebung nützlich sein, in der die Verbindungsinformationen extern verwaltet und an die Umgebung übergeben werden.
export PGPASSWORD="secret"export PGHOST=localhostexport PGUSER=ownerexport PGDATABASE=mydatabaseUm sich dann zu verbinden, starten Sie den Prozess duckdb und führen Sie aus:
ATTACH '' AS p (TYPE postgres);Verwendung
Die Tabellen in der PostgreSQL-Datenbank können gelesen werden, als wären sie normale DuckDB-Tabellen, die zugrunde liegenden Daten werden jedoch zur Abfragezeit direkt aus PostgreSQL gelesen.
SHOW ALL TABLES;| name |
|---|
| uuids |
SELECT * FROM uuids;| u |
|---|
| 6d3d2541-710b-4bde-b3af-4711738636bf |
| NULL |
| 00000000-0000-0000-0000-000000000001 |
| ffffffff-ffff-ffff-ffff-ffffffffffff |
Es kann wünschenswert sein, eine Kopie der PostgreSQL-Datenbanken in DuckDB zu erstellen, damit das System die Tabellen nicht ständig erneut aus PostgreSQL liest, insbesondere bei großen Tabellen.
Daten können mit Standard-SQL von PostgreSQL nach DuckDB kopiert werden, zum Beispiel:
CREATE TABLE duckdb_table AS FROM postgres_db.postgres_tbl;Daten nach PostgreSQL schreiben
Zusätzlich zum Lesen von Daten aus PostgreSQL ermöglicht die Erweiterung das Erstellen von Tabellen, das Laden von Daten in PostgreSQL und andere Änderungen an einer PostgreSQL-Datenbank mit Standard-SQL-Abfragen.
Damit können Sie DuckDB beispielsweise verwenden, um in einer PostgreSQL-Datenbank gespeicherte Daten nach Parquet zu exportieren oder Daten aus einer Parquet-Datei in PostgreSQL zu lesen.
Nachfolgend ein kurzes Beispiel, wie Sie eine neue Tabelle in PostgreSQL erstellen und Daten darin laden.
ATTACH 'dbname=postgresscanner' AS postgres_db (TYPE postgres);CREATE TABLE postgres_db.tbl (id INTEGER, name VARCHAR);INSERT INTO postgres_db.tbl VALUES (42, 'DuckDB');Viele Operationen auf PostgreSQL-Tabellen werden unterstützt. Alle diese Operationen ändern die PostgreSQL-Datenbank direkt, und das Ergebnis nachfolgender Operationen kann dann mit PostgreSQL gelesen werden.
Beachten Sie: Wenn Änderungen nicht erwünscht sind, kann ATTACH mit der Eigenschaft READ_ONLY ausgeführt werden, die Änderungen an der zugrunde liegenden Datenbank verhindert. Zum Beispiel:
ATTACH 'dbname=postgresscanner' AS postgres_db (TYPE postgres, READ_ONLY);Nachfolgend eine Liste unterstützter Operationen.
CREATE TABLE
CREATE TABLE postgres_db.tbl (id INTEGER, name VARCHAR);INSERT INTO
INSERT INTO postgres_db.tbl VALUES (42, 'DuckDB');SELECT
SELECT * FROM postgres_db.tbl;| id | name |
|---|---|
| 42 | DuckDB |
COPY
Sie können Tabellen zwischen PostgreSQL und DuckDB hin- und herkopieren:
COPY postgres_db.tbl TO 'data.parquet';COPY postgres_db.tbl FROM 'data.parquet';Diese Kopien verwenden die binäre PostgreSQL-Wire-Kodierung. DuckDB kann Daten mit dieser Kodierung auch in eine Datei schreiben, die Sie anschließend mit einem Client Ihrer Wahl in PostgreSQL laden können, wenn Sie die Verbindungsverwaltung selbst übernehmen möchten:
COPY 'data.parquet' TO 'pg.bin' WITH (FORMAT postgres_binary);Die erzeugte Datei entspricht dem, was Sie erhalten, wenn Sie die Datei mit DuckDB nach PostgreSQL kopieren und sie dann mit psql oder einem anderen Client aus PostgreSQL ausgeben:
DuckDB:
COPY postgres_db.tbl FROM 'data.parquet';PostgreSQL:
\copy tbl TO 'data.bin' WITH (FORMAT BINARY);Sie können auch eine vollständige Kopie der Datenbank mit der Anweisung COPY FROM DATABASE erstellen:
COPY FROM DATABASE postgres_db TO my_duckdb_db;UPDATE
UPDATE postgres_db.tblSET name = 'Woohoo'WHERE id = 42;DELETE
DELETE FROM postgres_db.tblWHERE id = 42;ALTER TABLE
ALTER TABLE postgres_db.tblADD COLUMN k INTEGER;DROP TABLE
DROP TABLE postgres_db.tbl;CREATE VIEW
CREATE VIEW postgres_db.v1 AS SELECT 42;CREATE SCHEMA / DROP SCHEMA
CREATE SCHEMA postgres_db.s1;CREATE TABLE postgres_db.s1.integers (i INTEGER);INSERT INTO postgres_db.s1.integers VALUES (42);SELECT * FROM postgres_db.s1.integers;| i |
|---|
| 42 |
DROP SCHEMA postgres_db.s1;DETACH
DETACH postgres_db;Transaktionen
CREATE TABLE postgres_db.tmp (i INTEGER);BEGIN;INSERT INTO postgres_db.tmp VALUES (42);SELECT * FROM postgres_db.tmp;Das gibt zurück:
| i |
|---|
| 42 |
ROLLBACK;SELECT * FROM postgres_db.tmp;Das gibt eine leere Tabelle zurück.
SQL-Abfragen in PostgreSQL ausführen
Die Tabellenfunktion postgres_query
Die Tabellenfunktion postgres_query ermöglicht es, beliebige Leseabfragen in einer angehängten Datenbank auszuführen. postgres_query nimmt den Namen der angehängten PostgreSQL-Datenbank, in der die Abfrage ausgeführt werden soll, sowie die auszuführende SQL-Abfrage entgegen. Das Ergebnis der Abfrage wird zurückgegeben. Einfache Anführungszeichen in Strings werden durch Wiederholen des einfachen Anführungszeichens escaped.
postgres_query(attached_database::VARCHAR, query::VARCHAR)Zum Beispiel:
ATTACH 'dbname=postgresscanner' AS postgres_db (TYPE postgres);SELECT * FROM postgres_query('postgres_db', 'SELECT * FROM cars LIMIT 3');| brand | model | color |
|---|---|---|
| Ferrari | Testarossa | red |
| Aston Martin | DB2 | blue |
| Bentley | Mulsanne | gray |
Die Funktion postgres_execute
Die Funktion postgres_execute ermöglicht das Ausführen beliebiger Abfragen in PostgreSQL, einschließlich Anweisungen, die Schema und Inhalt der Datenbank ändern.
ATTACH 'dbname=postgresscanner' AS postgres_db (TYPE postgres);CALL postgres_execute('postgres_db', 'CREATE TABLE my_table (i INTEGER)');Einstellungen
Die Erweiterung stellt die folgenden Konfigurationsparameter bereit.
| Name | Beschreibung | Standard |
|---|---|---|
pg_array_as_varchar |
PostgreSQL-Arrays als varchar lesen – ermöglicht das Lesen von Arrays mit gemischter Dimensionalität | false |
pg_connection_cache |
Ob der Verbindungscache verwendet werden soll | true |
pg_connection_limit |
Die maximale Anzahl gleichzeitiger PostgreSQL-Verbindungen | 64 |
pg_debug_show_queries |
DEBUG-EINSTELLUNG: alle an PostgreSQL gesendeten Abfragen auf stdout ausgeben | false |
pg_experimental_filter_pushdown |
Ob Filter-Pushdown verwendet werden soll (derzeit experimentell) | true |
pg_pages_per_task |
Die Anzahl der Seiten pro Task | 1000 |
pg_use_binary_copy |
Ob BINARY-Copy zum Lesen von Daten verwendet werden soll | true |
pg_null_byte_replacement |
Beim Schreiben von NULL-Bytes nach Postgres diese durch das angegebene Zeichen ersetzen | NULL |
pg_use_ctid_scan |
Ob das Scannen über Tabellen-ctids parallelisiert werden soll | true |
Schema-Cache
Um Schema-Daten nicht ständig aus PostgreSQL holen zu müssen, hält DuckDB Schema-Informationen – etwa Tabellennamen, ihre Spalten usw. – im Cache. Wenn Schemaänderungen über eine andere Verbindung zur PostgreSQL-Instanz vorgenommen werden, etwa neue Spalten zu einer Tabelle hinzugefügt werden, können die gecachten Schema-Informationen veraltet sein. In diesem Fall kann die Funktion pg_clear_cache ausgeführt werden, um die internen Caches zu leeren.
CALL pg_clear_cache();In Version 1.5.5 wurde Unterstützung für die automatische Erkennung von Schemaänderungen über eine „Staleness Query“ hinzugefügt (Beitrag von Brandon Freeman in duckdb/duckdb-postgres#514):
-
wenn die Option
pg_staleness_query_enabled(BOOLEAN, Standard:FALSE) aktiviert ist, wird bei jedem Katalogzugriff eine Abfrage ausgeführt, die den Wert der Spaltepg_class.xminvon Postgres in jeder Tabelle prüft und den Cache automatisch neu lädt, wenn eine Änderung erkannt wird -
für Postgres-Wire-kompatible Datenbanken kann eine eigene „Staleness Query“ über die Option
pg_staleness_querygesetzt werden.
Arbeiten mit hstore-Spalten
DuckDB gibt Daten aus hstore-Spalten als VARCHAR ihrer Textdarstellung zurück, etwa key=>value, foo=>bar.
Sie können die Funktion postgres_hstore_get
verwenden, um den Wert für einen gegebenen Schlüssel zu lesen, oder postgres_hstore_to_json,
um das gesamte Schlüssel/Wert-Paar-Set für die weitere Verarbeitung nach JSON zu konvertieren.
SELECT postgres_hstore_get('a=>b, c=>d', 'a');-- b
SELECT postgres_hstore_get('a=>b, c=>d', 'missingkey');-- NULL
SELECT postgres_hstore_to_json('a=>b, c=>d, e => null');-- {"a": "b", "c": "d", e: null}