本节提供有关 dbt 与 ClickHouse 可用部分功能的文档说明。
Profile.yml 配置
如需通过 dbt 连接到 ClickHouse,您需要在 profiles.yml 文件中添加一个 profile。ClickHouse 的 profile 需符合以下语法:
your_profile_name:
target: dev
outputs:
dev:
type: clickhouse
# Optional
schema: [default] # ClickHouse database for dbt models
driver: [http] # http or native. If not set this will be autodetermined based on port setting
host: [localhost]
port: [8123] # If not set, defaults to 8123, 8443, 9000, 9440 depending on the secure and driver settings
user: [default] # User for all database operations
password: [<empty string>] # Password for the user
cluster: [<empty string>] # If set, certain DDL/table operations will be executed with the `ON CLUSTER` clause using this cluster. Distributed materializations require this setting to work. See the following ClickHouse Cluster section for more details.
verify: [True] # Validate TLS certificate if using TLS/SSL
secure: [False] # Use TLS (native protocol) or HTTPS (http protocol)
client_cert: [null] # Path to a TLS client certificate in .pem format
client_cert_key: [null] # Path to the private key for the TLS client certificate
server_host_name: [null] # Override the TLS SNI and hostname verification target. Useful when connecting via a DNS alias (e.g. an internal CNAME or AWS PrivateLink endpoint) where the TLS certificate is issued for a different hostname than the one used in `host`.
retries: [1] # Number of times to retry a "retriable" database exception (such as a 503 'Service Unavailable' error)
compression: [<empty string>] # Use gzip compression if truthy (http), or compression type for a native connection
connect_timeout: [10] # Timeout in seconds to establish a connection to ClickHouse
send_receive_timeout: [300] # Timeout in seconds to receive data from the ClickHouse server
cluster_mode: [False] # Use specific settings designed to improve operation on Replicated databases (recommended for ClickHouse Cloud)
use_lw_deletes: [False] # Use the strategy `delete+insert` as the default incremental strategy.
check_exchange: [True] # Validate that clickhouse support the atomic EXCHANGE TABLES command. (Not needed for most ClickHouse versions)
local_suffix: [_local] # Table suffix of local tables on shards for distributed materializations.
local_db_prefix: [<empty string>] # Database prefix of local tables on shards for distributed materializations. If empty, it uses the same database as the distributed table.
allow_automatic_deduplication: [False] # Enable ClickHouse automatic deduplication for Replicated tables
tcp_keepalive: [False] # Native client only, specify TCP keepalive configuration. Specify custom keepalive settings as [idle_time_sec, interval_sec, probes].
reuse_connections: [True] # Re-use the same connection across models. Set to `False` to close the connection at the end of each model — useful on multi-replica ClickHouse Cloud services where the load balancer routes by TCP connection. Note: disabling connection reuse adds a new TCP/TLS handshake per model, which increases total `dbt run` wall time (typically ~200-500 ms per model). Combine with `threads > 1` for the best balance between distribution and throughput.
custom_settings: [{}] # A dictionary/mapping of custom ClickHouse settings for the connection - default is empty.
database_engine: '' # Database engine to use when creating new ClickHouse schemas (databases). If not set (the default), new databases will use the default ClickHouse database engine (usually Atomic).
threads: [1] # Number of threads to use when running queries. Before setting it to a number higher than 1, make sure to read the [read-after-write consistency](#read-after-write-consistency) section.
# Native (clickhouse-driver) connection settings
sync_request_timeout: [5] # Timeout for server ping
compress_block_size: [1048576] # Compression block size if compression is enabledschema 与 数据库
dbt 模型的 relation 标识符 database.schema.table 与 ClickHouse 不兼容,因为 ClickHouse 不支持 schema。
因此,我们采用简化形式 schema.table,其中 schema 表示 ClickHouse 的 数据库。不建议使用 default 数据库。
SET 语句警告
在许多环境中,使用 SET 语句让某个 ClickHouse 设置在所有 DBT 查询中持续生效并不可靠, 而且可能导致意外失败。尤其是在通过负载均衡器使用 HTTP 连接时,因为负载均衡器会将查询 分发到多个节点 (例如 ClickHouse Cloud) ;不过在某些情况下,使用 ClickHouse 原生连接时也可能 出现这种问题。因此,作为最佳实践,我们建议将所需的 ClickHouse 设置配置在 DBT profile 的 “custom_settings” 属性中,而不要依赖 pre-hook 的 “SET” 语句,尽管这种做法偶尔也会被建议采用。
设置 quote_columns
为避免出现警告,请务必在 dbt_project.yml 中为 quote_columns 显式指定一个值。更多信息请参阅 quote_columns 文档。
seeds:
+quote_columns: false #如果 CSV 列标题中含有空格,则设为 `true`关于 ClickHouse 集群
使用 ClickHouse 集群时,需要考虑两点:
- 设置
cluster参数。 - 确保写后读一致性,尤其是在使用多个
threads时。
集群设置
profile 中的 cluster 设置可让 dbt-clickhouse 针对 ClickHouse 集群运行。如果在 profile 中设置了 cluster,默认情况下,所有模型都会使用 ON CLUSTER 子句创建——使用 Replicated 引擎的模型除外。这包括:
- 创建数据库
- 视图物化类型
- 表和增量物化类型
- 分布式物化类型
Replicated 引擎不会包含 ON CLUSTER 子句,因为它们旨在自行管理复制。
如果想让某个特定模型不使用基于集群的创建方式,请添加 disable_on_cluster 配置:
{{ config(
engine='MergeTree',
materialized='table',
disable_on_cluster='true'
)
}}使用非复制引擎的表和增量物化类型不会受到 cluster 设置的影响 (模型只会
在当前连接的节点上创建) 。
兼容性
如果某个模型在创建时未设置 cluster,dbt-clickhouse 会检测到这种情况,并在该模型上执行所有不带 on cluster 子句的 DDL/DML。
写后读一致性
dbt 依赖写入后读取一致性模型。如果无法保证所有操作都发送到同一个副本,那么它与拥有多个副本的 ClickHouse 集群并不兼容。你在日常使用 dbt 时可能不会遇到问题,但可以根据集群情况采用一些策略来确保这一点:
- 如果你使用的是 ClickHouse Cloud 集群,只需在 profile 的
custom_settings属性中设置select_sequential_consistency: 1。有关此设置的更多信息,请参见这里。 - 如果你使用的是自托管集群,请确保所有 dbt 请求都发送到同一个 ClickHouse 副本。如果上层有负载均衡器,请尝试使用某种
replica aware routing/sticky sessions机制,以确保始终访问同一个副本。在 ClickHouse Cloud 之外的集群中添加设置select_sequential_consistency = 1不推荐。
其他 ClickHouse 宏
模型物化实用宏
以下宏用于简化创建 ClickHouse 特有的表和视图:
engine_clause– 使用engine模型配置属性来指定 ClickHouse 表引擎。dbt-clickhouse 默认使用MergeTree引擎。partition_cols– 使用partition_by模型配置属性来指定 ClickHouse 分区键。默认不指定 分区键。order_cols– 使用order_by模型配置来指定 ClickHouse 的 ORDER BY/排序键。如果未指定, ClickHouse 将使用空的 tuple(),并且该表将处于未排序状态primary_key_clause– 使用primary_key模型配置属性来指定 ClickHouse 主键。默认情况下, 会设置主键,ClickHouse 将使用 ORDER BY 子句作为主键。on_cluster_clause– 使用clusterprofile 属性为某些 dbt 操作添加ON CLUSTER子句: Distributed 物化、视图创建和数据库创建。ttl_config– 使用ttl模型配置属性来指定 ClickHouse 表生存时间 (TTL) 表达式。默认不指定 TTL。
s3Source 辅助宏
s3source 宏简化了通过 ClickHouse S3 表函数直接从 S3 选择 ClickHouse 数据的过程。它的工作原理是,
从一个具名配置字典中填充 S3 表函数的参数 (该字典名称必须以
s3 结尾) 。该宏
会先在 profile 的 vars 中查找该字典,然后再在模型配置中查找。该字典可以包含以下任意
键,用于填充 S3 表函数的
参数:
| 参数名称 | 描述 |
|---|---|
| bucket | bucket 的基础 URL,例如 https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi。如果未提供协议,则默认使用 https://。 |
| path | 用于表查询的 S3 路径,例如 /trips_4.gz。支持 S3 通配符。 |
| fmt | 引用的 S3 对象所预期的 ClickHouse 输入格式 (例如 TSV 或 CSVWithNames) 。 |
| structure | bucket 中数据的列结构,以名称/数据类型对列表表示,例如 ['id UInt32', 'date DateTime', 'value String']。如果未提供,ClickHouse 将推断该结构。 |
| aws_access_key_id | S3 访问密钥 ID。 |
| aws_secret_access_key | S3 密钥。 |
| role_arn | 为安全访问 S3 而创建的 IAM role 的 ARN。更多信息请参见此文档。 |
| external_id | 担任 IAM role 时与 role_arn 一并传递的外部 ID。需要设置 role_arn。自 dbt-clickhouse 1.10.2 起可用。 |
| compression | S3 对象使用的压缩方法。如果未提供,ClickHouse 将尝试根据文件名判断压缩方式。 |
示例
在 dbt_project.yml 中定义共享配置 (字典名称必须以 s3 结尾) :
vars:
taxi_s3:
bucket: 'datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi'
fmt: 'TabSeparatedWithNames'然后在模型中调用该宏。上述任一参数也可在调用时直接传入,并优先于字典配置值:
select * from {{ clickhouse_s3source('taxi_s3', path='/trips_4.gz') }}更多示例请参见 S3 测试文件。
跨数据库宏支持
dbt-clickhouse 现已支持 dbt Core 中包含的大多数跨数据库宏,但以下情况除外:
- ClickHouse 中的
split_partSQL 函数是通过 splitByChar 函数实现的。该函数要求 “split”分隔符必须使用常量字符串,因此此宏使用的delimeter参数会被 解释为字符串,而不是列名 - 同样,ClickHouse 中的
replaceSQL 函数要求old_chars和new_chars参数必须是常量字符串,因此调用此宏时,这些参数会被解释为字符串而不是列名。
目录支持
dbt 目录集成状态
dbt Core v1.10 引入了目录集成支持,使适配器能够将模型物化到管理 Apache Iceberg 等开放表格式的外部目录中。该功能尚未在 dbt-clickhouse 中原生实现。 你可以在 GitHub issue #489 中跟踪该功能实现的进展。
ClickHouse 目录支持
ClickHouse 最近新增了对 Apache Iceberg 表和数据目录的原生支持。大多数功能仍处于 experimental 阶段,但如果你使用的是较新的 ClickHouse 版本,已经可以使用这些功能。
-
你可以使用 ClickHouse,通过 Iceberg 表引擎 和 Iceberg 表函数 查询存储在对象存储中 (S3、Azure Blob 存储、Google Cloud Storage) 的 Iceberg 表。
-
此外,ClickHouse 还提供了 DataLakeCatalog 数据库引擎,可连接到外部数据目录,包括 AWS Glue Catalog、Databricks Unity Catalog、Hive Metastore 和 REST Catalog。这样,你就可以直接从外部目录查询开放表格式的数据 (Iceberg、Delta Lake) ,而无需复制数据。
使用 Iceberg 和目录的变通方案
如果你已经使用上述工具在 ClickHouse 集群中定义了 Iceberg 表或目录,就可以在 dbt 项目中从这些 Iceberg 表或目录读取数据。你可以利用 dbt 的 source 功能,在 dbt 项目中引用这些表。比如,如果你想访问 REST 目录中的表,可以:
- 创建一个指向外部目录的数据库:
-- 使用 REST Catalog 的示例
SET allow_experimental_database_iceberg = 1;
CREATE DATABASE iceberg_catalog
ENGINE = DataLakeCatalog('http://rest:8181/v1', 'admin', 'password')
SETTINGS
catalog_type = 'rest',
storage_endpoint = 'http://minio:9000/lakehouse',
warehouse = 'demo'- 在 dbt 中将目录数据库及其表定义为 source: 请注意,这些表应已在 ClickHouse 中可用
version: 2
sources:
- name: external_catalog
database: iceberg_catalog
tables:
- name: orders
- name: customers- 在 dbt 模型中使用目录中的表:
SELECT
o.order_id,
c.customer_name,
o.order_date
FROM {{ source('external_catalog', 'orders') }} o
INNER JOIN {{ source('external_catalog', 'customers') }} c
ON o.customer_id = c.customer_id关于这些变通方案的说明
这些变通方案的优点包括:
- 你可以立即使用不同类型的外部表和外部目录,无需等待原生 dbt 目录集成。
- 原生目录支持可用后,你也能顺畅迁移过去。
但目前仍有一些限制:
- **手动设置:**在 dbt 中引用 Iceberg 表和目录数据库之前,必须先在 ClickHouse 中手动创建它们。
- **不支持目录级 DDL:**dbt 无法管理目录级操作,例如在外部目录中创建或删除 Iceberg 表。因此,目前你还无法通过 dbt connector 创建这些表。未来可能会增加通过 Iceberg() 引擎创建表的能力。
- **写入操作:**目前,向 Iceberg/Data Catalog 表写入的能力仍然有限。请查阅 ClickHouse 文档,了解当前可用的选项。