Zum Inhalt springen

Azure-Erweiterung

Die Erweiterung azure ist eine ladbare Erweiterung, die DuckDB um eine Dateisystemabstraktion für Azure Blob Storage ergänzt und so sowohl das Lesen als auch das Schreiben von Daten ermöglicht.

Installation und Laden

Die Erweiterung azure wird beim ersten Einsatz transparent aus dem offiziellen Erweiterungs-Repository automatisch geladen. Wenn Sie sie manuell installieren und laden möchten, führen Sie aus:

INSTALL azure;
LOAD azure;

Verwendung

Sobald die Authentifizierung eingerichtet ist, können Sie Azure Storage wie folgt abfragen:

Azure Blob Storage

Erlaubte URI-Schemata: az oder azure

SELECT count(*)
FROM 'az://⟨my_container⟩/⟨path⟩/⟨my_file⟩.⟨parquet_or_csv⟩';

Globs werden ebenfalls unterstützt:

SELECT *
FROM 'az://⟨my_container⟩/⟨path⟩/*.csv';
SELECT *
FROM 'az://⟨my_container⟩/⟨path⟩/**';

Oder mit vollständig qualifizierter Pfadsyntax:

SELECT count(*)
FROM 'az://⟨my_storage_account⟩.blob.core.windows.net/⟨my_container⟩/⟨path⟩/⟨my_file⟩.⟨parquet_or_csv⟩';
SELECT *
FROM 'az://⟨my_storage_account⟩.blob.core.windows.net/⟨my_container⟩/⟨path⟩/*.csv';

Azure Data Lake Storage (ADLS)

Erlaubte URI-Schemata: abfss

SELECT count(*)
FROM 'abfss://⟨my_filesystem⟩/⟨path⟩/⟨my_file⟩.⟨parquet_or_csv⟩';

Globs werden ebenfalls unterstützt:

SELECT *
FROM 'abfss://⟨my_filesystem⟩/⟨path⟩/*.csv';
SELECT *
FROM 'abfss://⟨my_filesystem⟩/⟨path⟩/**';

Oder mit vollständig qualifizierter Pfadsyntax:

SELECT count(*)
FROM 'abfss://⟨my_storage_account⟩.dfs.core.windows.net/⟨my_filesystem⟩/⟨path⟩/⟨my_file⟩.⟨parquet_or_csv⟩';
SELECT *
FROM 'abfss://⟨my_storage_account⟩.dfs.core.windows.net/⟨my_filesystem⟩/⟨path⟩/*.csv';

In Azure Blob Storage schreiben

Sie können Daten mit der Anweisung COPY direkt nach Azure Blob oder ADLSv2 Storage schreiben.

-- Write query results to a Parquet file on Blob Storage
COPY (SELECT * FROM my_table)
TO 'az://⟨my_container⟩/⟨path⟩/output.parquet';
-- Write a table to a CSV file on ADLSv2 Storage
COPY my_table
TO 'abfss://⟨my_container⟩/⟨path⟩/output.csv';

Sie können auch vollständig qualifizierte Pfade verwenden:

COPY my_table
TO 'az://⟨my_storage_account⟩.blob.core.windows.net/⟨my_container⟩/⟨path⟩/output.parquet';

Konfiguration

Verwenden Sie die folgenden Konfigurationsoptionen, um zu steuern, wie die Erweiterung Remote-Dateien liest:

Name Description Type Default
azure_http_stats HTTP-Informationen von Azure Storage in die Anweisung EXPLAIN ANALYZE aufnehmen. BOOLEAN false
azure_read_transfer_concurrency Maximale Anzahl Threads, die der Azure-Client für einen einzelnen parallelen Lesevorgang nutzen kann. Ist azure_read_transfer_chunk_size kleiner als azure_read_buffer_size, erlaubt ein Wert > 1 dem Azure-Client, den Puffer mit parallelen Anfragen zu füllen. BIGINT 5
azure_read_transfer_chunk_size Maximale Größe in Bytes, die der Azure-Client in einer einzelnen Anfrage liest. Es wird empfohlen, dass dieser Wert ein Faktor von azure_read_buffer_size ist. BIGINT 1024*1024
azure_read_buffer_size Größe des Lesepuffers. Es wird empfohlen, dass dieser Wert gleichmäßig durch azure_read_transfer_chunk_size teilbar ist. UBIGINT 1024*1024
azure_transport_option_type Zugrunde liegender Adapter im Azure SDK. Gültige Werte: default oder curl. VARCHAR default
azure_context_caching Caching der zugrunde liegenden HTTP-Verbindung des Azure SDK im DuckDB-Verbindungskontext bei Abfragen ein- oder ausschalten. Wenn Sie vermuten, dass das Nebenwirkungen hat, können Sie es auf false setzen (nicht empfohlen). BOOLEAN true

Wenn Sie azure_transport_option_type explizit auf curl setzen, hat das folgende Auswirkungen:

  • Unter Linux kann das Zertifikatsprobleme lösen (Error: Invalid Error: Fail to get a new connection for: https://storage_account_name.blob.core.windows.net/. Problem with the SSL CA cert (path? access rights?)), weil die Erweiterung beim expliziten Setzen das Zertifikatsbundle in verschiedenen Pfaden sucht (das macht curl standardmäßig nicht und kann durch statisches Linken falsch sein).
  • Unter Windows ersetzt das den Standardadapter (WinHTTP) und ermöglicht alle curl-Fähigkeiten (z. B. SOCKS-Proxys).
  • Auf allen Betriebssystemen werden die folgenden Umgebungsvariablen berücksichtigt:
    • CURL_CA_INFO: Pfad zu einer PEM-kodierten Datei mit den an libcurl übergebenen Zertifizierungsstellen. Diese Option funktioniert bekanntermaßen nur unter Linux und kann auf anderen Plattformen einen Fehler auslösen.
    • CURL_CA_PATH: Pfad zu einem Verzeichnis mit PEM-kodierten Dateien, die die an libcurl übergebenen Zertifizierungsstellen enthalten.

Beispiel:

SET azure_http_stats = false;
SET azure_read_transfer_concurrency = 5;
SET azure_read_transfer_chunk_size = 1_048_576;
SET azure_read_buffer_size = 1_048_576;

Authentifizierung

Die Azure-Erweiterung bietet zwei Wege, die Authentifizierung zu konfigurieren. Der bevorzugte Weg sind Secrets.

Authentifizierung mit Secret

Für die Azure-Erweiterung stehen mehrere Secret Provider zur Verfügung:

  • Wenn Sie für verschiedene Storage Accounts unterschiedliche Secrets brauchen, verwenden Sie die Konfiguration SCOPE. Beachten Sie, dass SCOPE einen abschließenden Schrägstrich braucht (SCOPE 'azure://some_container/').
  • Bei vollständig qualifiziertem Pfad ist das Attribut ACCOUNT_NAME optional.

Provider CONFIG

Der Standard-Provider CONFIG (also benutzerkonfiguriert) erlaubt Zugriff auf den Storage Account über einen Connection String oder anonym. Beispiel:

CREATE SECRET secret1 (
TYPE azure,
CONNECTION_STRING '⟨value⟩'
);

Wenn Sie keine Authentifizierung verwenden, müssen Sie trotzdem den Namen des Storage Accounts angeben. Beispiel:

CREATE SECRET secret2 (
TYPE azure,
PROVIDER config,
ACCOUNT_NAME '⟨storage_account_name⟩'
);

Der Standard-PROVIDER ist CONFIG.

Provider credential_chain

Der Provider credential_chain verbindet sich mit Zugangsdaten, die das Azure SDK automatisch über die Azure Credential Chain holt. Standardmäßig wird die Kette DefaultAzureCredential verwendet, die Zugangsdaten in der von der Azure-Dokumentation angegebenen Reihenfolge versucht. Beispiel:

CREATE SECRET secret3 (
TYPE azure,
PROVIDER credential_chain,
ACCOUNT_NAME '⟨storage_account_name⟩'
);

DuckDB erlaubt außerdem, mit dem Schlüsselwort CHAIN eine bestimmte Kette anzugeben. Das ist eine durch Semikolon getrennte Liste (a;b;c) von Providern, die der Reihe nach versucht werden. Beispiel:

CREATE SECRET secret4 (
TYPE azure,
PROVIDER credential_chain,
CHAIN 'cli;env',
ACCOUNT_NAME '⟨storage_account_name⟩'
);

Mögliche Werte sind: cli; managed_identity; workload_identity; env; default;

Wenn keine explizite CHAIN angegeben ist, wird die Standardkette default verwendet.

Managed Identity

Managed Identity (MI) kann über credential_chain ohne Extraaufwand und automatisch genutzt werden. In typischen Fällen, in denen dem Executor nur eine einzige MI zur Verfügung steht, ist keine Konfiguration nötig.

Hat Ihre Ausführungsumgebung mehrere Identitäten, verwenden Sie den Provider MANAGED_IDENTITY und geben Sie an, welche Identität genutzt werden soll. Dieser Provider erlaubt die Angabe der Identität über eines von CLIENT_ID, OBJECT_ID oder RESOURCE_ID, z. B.:

CREATE SECRET secret1 (
TYPE AZURE,
PROVIDER MANAGED_IDENTITY,
ACCOUNT_NAME '⟨storage account name⟩',
CLIENT_ID '⟨used-assigned managed identity client id⟩'
);

Der Provider kann auch ohne Angabe einer ID verwendet werden; wenn nur eine einzige ID verfügbar ist, verhält er sich identisch zum Provider credential_chain und nutzt die eine verfügbare ID. Sind mehrere IDs verfügbar, ist das Verhalten undefiniert (genauer: durch das Azure SDK definiert) – in dieser Situation empfehlen wir daher, die Identität explizit zu setzen.

Provider SERVICE_PRINCIPAL

Der Provider SERVICE_PRINCIPAL verbindet sich über einen Azure Service Principal (SPN).

Entweder mit einem Secret:

CREATE SECRET azure_spn (
TYPE azure,
PROVIDER service_principal,
TENANT_ID '⟨tenant_id⟩',
CLIENT_ID '⟨client_id⟩',
CLIENT_SECRET '⟨client_secret⟩',
ACCOUNT_NAME '⟨storage_account_name⟩'
);

Oder mit einem Zertifikat:

CREATE SECRET azure_spn_cert (
TYPE azure,
PROVIDER service_principal,
TENANT_ID '⟨tenant_id⟩',
CLIENT_ID '⟨client_id⟩',
CLIENT_CERTIFICATE_PATH '⟨client_cert_path⟩',
ACCOUNT_NAME '⟨storage_account_name⟩'
);

Proxy konfigurieren

Um Proxy-Informationen bei der Verwendung von Secrets festzulegen, können Sie HTTP_PROXY, PROXY_USER_NAME und PROXY_PASSWORD in der Secret-Definition ergänzen. Beispiel:

CREATE SECRET secret5 (
TYPE azure,
CONNECTION_STRING '⟨value⟩',
HTTP_PROXY 'http://localhost:3128',
PROXY_USER_NAME 'john',
PROXY_PASSWORD 'doe'
);
  • Bei Secrets wird die Umgebungsvariable HTTP_PROXY weiterhin berücksichtigt, außer Sie geben explizit einen Wert an.
  • Bei Secrets wird die SET-Variable der Sitzung Authentifizierung mit Variablen ignoriert.
  • Beim Azure-Provider credential_chain wird das eigentliche Token zur Abfragezeit geholt, nicht beim Anlegen des Secrets.

Authentifizierung mit Variablen (veraltet)

SET variable_name = variable_value;

Dabei kann variable_name einer der folgenden Werte sein:

Name Description Type Default
azure_storage_connection_string Azure-Connection-String zur Authentifizierung und Konfiguration von Azure-Anfragen. STRING -
azure_account_name Azure-Account-Name; wenn gesetzt, versucht die Erweiterung automatisch, Zugangsdaten zu erkennen (wird nicht verwendet, wenn Sie den Connection String übergeben). STRING -
azure_endpoint Überschreibt den Azure-Endpunkt, wenn die Azure-Credential-Provider verwendet werden. STRING blob.core.windows.net
azure_credential_chain Geordnete Liste von Azure-Credential-Providern im String-Format, getrennt durch ;. Beispiel: 'cli;managed_identity;env'. Siehe die möglichen Werte im Abschnitt zum Provider credential_chain. Wird nicht verwendet, wenn Sie den Connection String übergeben. STRING -
azure_http_proxy Proxy für Login und Anfragen an Azure. STRING Umgebungsvariable HTTP_PROXY (falls gesetzt).
azure_proxy_user_name HTTP-Proxy-Benutzername, falls nötig. STRING -
azure_proxy_password HTTP-Proxy-Passwort, falls nötig. STRING -

Weitere Informationen

Logging

Die Azure-Erweiterung stützt sich auf das Azure SDK für die Verbindung zu Azure Blob Storage und kann die SDK-Logs auf die Konsole ausgeben. Um die Log-Stufe zu steuern, setzen Sie die Umgebungsvariable AZURE_LOG_LEVEL.

Ausführliche Logs können in Python beispielsweise so aktiviert werden:

import os
import duckdb
os.environ["AZURE_LOG_LEVEL"] = "verbose"
duckdb.sql("CREATE SECRET myaccount (TYPE azure, PROVIDER credential_chain, SCOPE 'az://myaccount.blob.core.windows.net/')")
duckdb.sql("SELECT count(*) FROM 'az://myaccount.blob.core.windows.net/path/to/blob.parquet'")

Unterschied zwischen ADLS und Blob Storage

Obwohl ADLS ähnliche Funktionen wie Blob Storage umsetzt, gibt es beim Globbing – besonders bei (komplexen) Glob-Mustern – deutliche Leistungsvorteile durch die ADLS-Endpunkte.

Zur Veranschaulichung ein Beispiel, wie ein Glob intern über den Blob- bzw. den ADLS-Endpunkt ausgeführt wird.

Mit dem folgenden Dateisystem:

root
├── l_receipmonth=1997-10
│ ├── l_shipmode=AIR
│ │ └── data_0.csv
│ ├── l_shipmode=SHIP
│ │ └── data_0.csv
│ └── l_shipmode=TRUCK
│ └── data_0.csv
├── l_receipmonth=1997-11
│ ├── l_shipmode=AIR
│ │ └── data_0.csv
│ ├── l_shipmode=SHIP
│ │ └── data_0.csv
│ └── l_shipmode=TRUCK
│ └── data_0.csv
└── l_receipmonth=1997-12
├── l_shipmode=AIR
│ └── data_0.csv
├── l_shipmode=SHIP
│ └── data_0.csv
└── l_shipmode=TRUCK
└── data_0.csv

Wird die folgende Abfrage über den Blob-Endpunkt ausgeführt:

SELECT count(*)
FROM 'az://root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv';

Dann erfolgen diese Schritte:

  • Alle Dateien mit dem Präfix root/l_receipmonth=1997- auflisten
    • root/l_receipmonth=1997-10/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-10/l_shipmode=AIR/data_0.csv
    • root/l_receipmonth=1997-10/l_shipmode=TRUCK/data_0.csv
    • root/l_receipmonth=1997-11/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-11/l_shipmode=AIR/data_0.csv
    • root/l_receipmonth=1997-11/l_shipmode=TRUCK/data_0.csv
    • root/l_receipmonth=1997-12/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-12/l_shipmode=AIR/data_0.csv
    • root/l_receipmonth=1997-12/l_shipmode=TRUCK/data_0.csv
  • Das Ergebnis mit dem angefragten Muster root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv filtern
    • root/l_receipmonth=1997-10/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-11/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-12/l_shipmode=SHIP/data_0.csv

Dieselbe Abfrage kann über den Data-Lake-Endpunkt so ausgeführt werden:

SELECT count(*)
FROM 'abfss://root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv';

Dann erfolgen diese Schritte:

  • Alle Verzeichnisse in root/ auflisten
    • root/l_receipmonth=1997-10
    • root/l_receipmonth=1997-11
    • root/l_receipmonth=1997-12
  • Filtern und Unterverzeichnisse auflisten: root/l_receipmonth=1997-10, root/l_receipmonth=1997-11, root/l_receipmonth=1997-12
    • root/l_receipmonth=1997-10/l_shipmode=SHIP
    • root/l_receipmonth=1997-10/l_shipmode=AIR
    • root/l_receipmonth=1997-10/l_shipmode=TRUCK
    • root/l_receipmonth=1997-11/l_shipmode=SHIP
    • root/l_receipmonth=1997-11/l_shipmode=AIR
    • root/l_receipmonth=1997-11/l_shipmode=TRUCK
    • root/l_receipmonth=1997-12/l_shipmode=SHIP
    • root/l_receipmonth=1997-12/l_shipmode=AIR
    • root/l_receipmonth=1997-12/l_shipmode=TRUCK
  • Filtern und Unterverzeichnisse auflisten: root/l_receipmonth=1997-10/l_shipmode=SHIP, root/l_receipmonth=1997-11/l_shipmode=SHIP, root/l_receipmonth=1997-12/l_shipmode=SHIP
    • root/l_receipmonth=1997-10/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-11/l_shipmode=SHIP/data_0.csv
    • root/l_receipmonth=1997-12/l_shipmode=SHIP/data_0.csv

Weil der Blob-Endpunkt keine Verzeichnisse kennt, kann der Filter erst nach dem Auflisten angewendet werden, während der ADLS-Endpunkt Dateien rekursiv auflistet. Besonders bei höherer Anzahl von Partitionen bzw. Verzeichnissen kann der Leistungsunterschied sehr groß sein.