Перейти к основному содержимому

DuckDB и Apache Iceberg

Только для dbt v2

Для поддержки catalogs.yml в DuckDB требуется dbt v2 с включённым флагом поведения use_catalogs_v2. Эта возможность недоступна в устаревшем Python-адаптере dbt-duckdb для dbt v1.

dbt_project.yml
flags:
use_catalogs_v2: true

В отличие от Snowflake, Databricks и BigQuery, DuckDB не поставляется с единым встроенным «управляемым» каталогом Iceberg. Это означает, что в DuckDB нельзя обойтись одним лишь table_format='iceberg' — для каждой модели Iceberg требуется catalog_name, указывающий на запись в catalogs.yml.

dbt поддерживает создание таблиц Iceberg для двух материализаций DuckDB:

Как DuckDB подключает каталоги​

Когда вы настраиваете каталог с блоком duckdb в catalogs.yml, dbt самостоятельно формирует и выполняет соответствующий оператор DuckDB ATTACH — вам не нужно писать SQL с ATTACH вручную. Затем dbt сопоставляет любую модель с соответствующим catalog_name с этой подключённой базой данных.

Каталоги Iceberg REST​

DuckDB может подключать любой каталог, реализующий протокол Iceberg REST, включая самостоятельно размещённые каталоги (например, Lakekeeper или Nessie), AWS Glue и AWS S3 Tables.

catalogs.yml
catalogs:
- name: rest_catalog
type: iceberg_rest
table_format: iceberg
config:
duckdb:
endpoint: "https://my-iceberg-rest.example.com"
secret: my_iceberg_secret
models/my_iceberg_model.sql
{{
config(
materialized = 'table',
catalog_name = 'rest_catalog'
)
}}

select * from {{ ref('jaffle_shop_customers') }}

Запустите модель командой dbt run -s my_iceberg_model. Вместо endpoint можно использовать endpoint_type: GLUE или endpoint_type: S3_TABLES, чтобы подключить одну из этих известных конечных точек Iceberg REST, управляемых AWS, без указания URL:

catalogs.yml
catalogs:
- name: s3_tables_catalog
type: iceberg_rest
table_format: iceberg
config:
duckdb:
endpoint_type: S3_TABLES
warehouse: "arn:aws:s3tables:us-east-1:123456789012:bucket/example"

Параметры endpoint и endpoint_type являются взаимоисключающими.

Запись в S3 Tables​

Для записи в S3 Tables используйте явно заданный endpoint с authorization_type: SIGV4.

В текущих предварительных сборках v2 сокращённая настройка endpoint_type: S3_TABLES работает для чтения, но при записи ошибочно использует OAuth2 вместо SigV4 по умолчанию. Это проявляется в виде одной из следующих ошибок:

Invalid Configuration Error: AUTHORIZATION_TYPE is 'oauth2', yet no 'secret' was provided...
InvalidArguments: HTTP Error: Failed to retrieve OAuth2 token from  (sqlstate: ...)

S3 Tables требует аутентификации SigV4. Пока эта проблема не исправлена, используйте конфигурацию с явно заданным endpoint и authorization_type: SIGV4. Для любого каталога S3 Tables, в который вы записываете данные, следуйте инструкциям из раздела Запись в Amazon S3 Tables.

Запись в Amazon S3 Tables​

Чтобы материализовать модели Iceberg в бакете S3 Tables, настройте каталог, учётные данные AWS и модель следующим образом.

Настройка каталога​

В catalogs.yml определите каталог iceberg_rest с явно заданной конечной точкой и аутентификацией SigV4, а также задайте параметры совместимости записи для S3 Tables:

catalogs.yml
catalogs:
- name: s3_tables_catalog
type: iceberg_rest
table_format: iceberg
config:
duckdb:
endpoint: "https://s3tables.<region>.amazonaws.com/iceberg"
warehouse: "arn:aws:s3tables:<region>:<account-id>:bucket/<bucket-name>"
authorization_type: SIGV4
secret: s3_tables_secret
default_schema: <namespace>
stage_create_tables: false # S3 Tables не поддерживает поэтапное создание через CREATE TABLE AS SELECT
disable_multi_table_commit: true # В S3 Tables нет конечной точки для фиксации транзакций с несколькими таблицами
purge_requested: true # S3 Tables допускает DROP TABLE только с включённым удалением файлов

Замените заполнители своим регионом AWS, идентификатором аккаунта, именем бакета таблиц и пространством имён.

secret ссылается на секрет типа s3 с цепочкой поставщиков учётных данных, определённый в profiles.yml (см. Секреты) — он предоставляет учётные данные SigV4, а не токен OAuth2.

Настройка учётных данных AWS​

В profiles.yml определите секрет типа s3 с тем же именем, которое вы использовали в catalogs.yml. Поставщик credential_chain предоставляет учётные данные AWS для аутентификации SigV4.

profiles.yml
my_profile:
target: dev
outputs:
dev:
type: duckdb
path: ':memory:'
extensions:
- iceberg
- aws
- httpfs
secrets:
- type: s3
name: s3_tables_secret
provider: credential_chain
region: <region>

Настройка модели​

Задайте для catalog_name имя вашего каталога, а для schema — пространство имён S3 Tables:

models/my_s3_tables_model.sql
{{
config(
materialized = 'table',
catalog_name = 's3_tables_catalog',
schema = '<namespace>'
)
}}

select * from {{ ref('jaffle_shop_customers') }}

Согласование схемы с пространством имён​

Поскольку схема DuckDB по умолчанию — main, стандартная логика именования схем в dbt объединяет её с пользовательской схемой модели (например, main_my_namespace), и полученное имя не совпадает с существующим пространством имён S3 Tables.

Добавьте переопределение на уровне проекта, чтобы итоговое имя схемы точно совпадало с вашим пространством имён:

macros/generate_schema_name.sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- if custom_schema_name is none -%}
{{ target.schema }}
{%- else -%}
{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}

Кроссплатформенный Mesh: чтение каталогов, управляемых другими платформами​

Поскольку одна запись каталога в catalogs.yml может одновременно содержать конфигурацию для нескольких платформ, вы можете направить DuckDB к тому же физическому каталогу, в который записывает данные Snowflake или Databricks — это позволяет использовать кроссплатформенный Mesh без копирования данных.

Snowflake Horizon​

Snowflake Horizon — это управляемый каталог Iceberg от Snowflake. Добавьте блок duckdb рядом с блоком snowflake, чтобы DuckDB мог подключить тот же каталог:

catalogs.yml
catalogs:
- name: horizon_catalog
type: horizon
table_format: iceberg
config:
snowflake:
external_volume: my_external_volume
duckdb:
warehouse: horizon_wh
endpoint: "https://horizon.example.com/catalog"
secret: horizon_secret
default_schema: demo

Databricks Unity Catalog​

Аналогично для Databricks Unity Catalog:

catalogs.yml
catalogs:
- name: unity_catalog
type: unity
table_format: iceberg
config:
databricks:
file_format: delta
use_uniform: true
duckdb:
warehouse: unity_wh
endpoint: "https://dbc-example.cloud.databricks.com/api/2.1/unity-catalog/iceberg"
default_schema: demo

Только чтение или чтение и запись​

По умолчанию dbt подключает каталоги Horizon и Unity в режиме чтения и записи (read_only: false) и применяет для каждого из них параметры ATTACH по умолчанию, обеспечивающие совместимость записи (например, отключает фиксацию транзакций с несколькими таблицами в Unity). Для записи в эти каталоги из DuckDB требуются DuckDB 1.5.4+ и duckdb-iceberg#1017. Если вам нужно только читать таблицы Iceberg, записанные другой платформой, задайте read_only: true:

      duckdb:
warehouse: horizon_wh
endpoint: "https://horizon.example.com/catalog"
read_only: true

DuckLake​

DuckLake — это отдельный открытый формат таблиц (не Apache Iceberg), созданный для DuckDB, но настраивается он точно так же, через catalogs.yml. Поскольку DuckLake не является Iceberg, в записях его каталогов используется table_format: default.

catalogs.yml
catalogs:
- name: local_lake
type: ducklake
table_format: default
config:
duckdb:
metadata_path: "metadata.ducklake"
data_path: "s3://my-bucket/lake" # необязательно
models/my_ducklake_model.sql
{{
config(
materialized = 'table',
catalog_name = 'local_lake'
)
}}

select * from {{ ref('jaffle_shop_customers') }}

dbt устанавливает расширение DuckLake и подключает каталог перед запуском вашей модели:

INSTALL ducklake
ATTACH IF NOT EXISTS 'ducklake:metadata.ducklake' AS local_lake (DATA_PATH 's3://my-bucket/lake')

Секреты​

Поле secret в блоке каталога duckdb ссылается на именованный секрет, определённый в profiles.yml, который dbt преобразует в оператор DuckDB CREATE SECRET:

profiles.yml
my_profile:
target: dev
outputs:
dev:
type: duckdb
path: ':memory:'
secrets:
- type: iceberg
name: my_iceberg_secret
# Дополнительные пары ключ-значение становятся параметрами CREATE SECRET
# (например, token, client_id, client_secret) — параметры для вашего каталога
# см. в документации расширения iceberg для DuckDB.

Для Amazon S3 Tables вместо этого используйте секрет с type: s3 / provider: credential_chain (SigV4, а не OAuth2 или аутентификацию по токену) — см. раздел Amazon S3 Tables (запись) выше.

Настройки каталогов Iceberg, специфичные для DuckDB​

Для каталогов horizon, unity и iceberg_rest можно задать следующие настройки внутри config.duckdb:

ПолеОбязательностьОписание
endpointОдин из параметров endpoint/endpoint_typeПолный URL каталога Iceberg REST.
endpoint_typeОдин из параметров endpoint/endpoint_typeGLUE или S3_TABLES для известных конечных точек, управляемых AWS. Для записи в S3 Tables предпочтительно явно задавать endpoint (см. предупреждение выше).
warehouseОбязательно для horizon; обязательно для любого каталога Amazon S3 Tables (как с endpoint_type: S3_TABLES, так и с явно заданным endpoint для записи)Идентификатор хранилища, передаваемый в качестве источника для ATTACH.
secretНеобязательноИмя секрета DuckDB из profiles.yml, используемого для аутентификации.
attach_asНеобязательноПереопределяет псевдоним подключения DuckDB. По умолчанию используется name каталога.
default_regionНеобязательноРегион AWS, если применимо.
default_schemaНеобязательноСхема/пространство имён по умолчанию в каталоге.
max_table_stalenessНеобязательноКак долго DuckDB может использовать кешированные метаданные до их обновления.
authorization_typeНеобязательноOAUTH2, SIGV4 или NONE. Нельзя сочетать с endpoint_type. Для записи в S3 Tables обязательно значение SIGV4.
access_delegation_modeНеобязательноVENDED_CREDENTIALS или NONE.
read_onlyНеобязательноПодключать каталог только для чтения. По умолчанию false (чтение и запись).
support_nested_namespacesНеобязательноПоддерживает ли каталог вложенные пространства имён.
stage_create_tablesНеобязательноСовместимость записи: использовать поэтапную запись для CREATE TABLE AS SELECT. Требуется DuckDB 1.5.4+. Для Amazon S3 Tables задайте false.
disable_multi_table_commitНеобязательноСовместимость записи: отключить фиксацию транзакций с несколькими таблицами. Требуется DuckDB 1.5.4+. Для Amazon S3 Tables задайте true.
skip_create_table_metadata_updatesНеобязательноСовместимость записи: пропускать обновления метаданных при CREATE TABLE. Требуется DuckDB 1.5.4+.
remove_files_on_deleteНеобязательноСовместимость записи: удалять соответствующие файлы данных при удалении таблицы. Требуется DuckDB 1.5.4+.
purge_requestedНеобязательноУдалять соответствующие файлы, если каталог поддерживает эту возможность. Для Amazon S3 Tables задайте true, поскольку этот сервис допускает DROP TABLE только с включённым удалением файлов.
encode_entire_prefixНеобязательноПрименять процентное кодирование ко всему префиксу ключа объекта.

Для каталогов ducklake в config.duckdb доступны следующие параметры:

ПолеОбязательностьОписание
metadata_pathОбязательноПуть к хранилищу метаданных DuckLake, например metadata.ducklake, или строка подключения к базе данных.
data_pathНеобязательноРасположение, в которое DuckLake записывает файлы данных.
attach_asНеобязательноПереопределяет псевдоним подключения DuckDB. По умолчанию используется name каталога.
metadata_schemaНеобязательноИспользуемая схема в хранилище метаданных.
metadata_catalogНеобязательноИмя каталога/базы данных в хранилище метаданных.
data_inlining_row_limitНеобязательноВстраивать группы строк, содержащие меньше указанного количества строк, в каталог метаданных вместо записи в файл Parquet.
create_if_not_existsНеобязательноСоздавать каталог DuckLake, если он ещё не существует.
read_onlyНеобязательноПодключать только для чтения.
encryptedНеобязательноШифровать каталог DuckLake.
automatic_migrationНеобязательноАвтоматически выполнять миграцию версии формата DuckLake в каталоге при подключении.
override_data_pathНеобязательноРазрешать подключение с data_path, отличающимся от пути, записанного в существующем каталоге.

Нашли ошибку?

0
Loading