azure
扩展是一个可加载扩展,为 Azure Blob 存储 添加了文件系统抽象到 DuckDB。
安装和加载
azure
扩展将在首次使用时从官方扩展仓库透明地自动加载。如果您想手动安装和加载,请运行
INSTALL azure;
LOAD azure;
用法
一旦身份验证设置完毕,您可以如下查询 Azure 存储
Azure Blob 存储
允许的 URI 方案:az
或 azure
SELECT count(*)
FROM 'az://my_container/path/my_file.parquet_or_csv';
也支持通配符
SELECT *
FROM 'az://my_container/path/*.csv';
SELECT *
FROM 'az://my_container/path/**';
或使用完全限定路径语法
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)
允许的 URI 方案:abfss
SELECT count(*)
FROM 'abfss://my_filesystem/path/my_file.parquet_or_csv';
也支持通配符
SELECT *
FROM 'abfss://my_filesystem/path/*.csv';
SELECT *
FROM 'abfss://my_filesystem/path/**';
或使用完全限定路径语法
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';
配置
使用以下配置选项来控制扩展如何读取远程文件
名称 | 描述 | 类型 | 默认值 |
---|---|---|---|
azure_http_stats |
在 EXPLAIN ANALYZE 语句中包含来自 Azure 存储的 HTTP 信息。 |
BOOLEAN |
false |
azure_read_transfer_concurrency |
Azure 客户端可用于单个并行读取的最大线程数。如果 azure_read_transfer_chunk_size 小于 azure_read_buffer_size ,则将此值设置为 > 1 将允许 Azure 客户端进行并发请求以填充缓冲区。 |
BIGINT |
5 |
azure_read_transfer_chunk_size |
Azure 客户端在单个请求中读取的最大字节大小。建议此值是 azure_read_buffer_size 的一个因子。 |
BIGINT |
1024*1024 |
azure_read_buffer_size |
读取缓冲区的大小。建议此值可被 azure_read_transfer_chunk_size 整除。 |
UBIGINT |
1024*1024 |
azure_transport_option_type |
Azure SDK 中使用的底层适配器。有效值为:default 或 curl 。 |
VARCHAR |
默认值 (default) |
azure_context_caching |
在执行查询时,启用/禁用 DuckDB 连接上下文中底层 Azure SDK HTTP 连接的缓存。如果您怀疑这会导致一些副作用,您可以尝试将其设置为 false 来禁用它(不推荐)。 | BOOLEAN |
true |
将
azure_transport_option_type
显式设置为curl
将产生以下效果
- 在 Linux 上,这可能会解决证书问题(
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?)
),因为在指定时,扩展将尝试在各种路径中查找捆绑证书(curl 默认不这样做,并且由于静态链接可能不正确)。- 在 Windows 上,这会替换默认适配器 (WinHTTP),允许您使用所有 curl 功能(例如使用 socks 代理)。
- 在所有操作系统上,它将遵守以下环境变量
CURL_CA_INFO
: PEM 编码文件路径,包含发送到 libcurl 的证书颁发机构。请注意,此选项已知仅适用于 Linux,如果在其他平台设置可能会报错。CURL_CA_PATH
: 目录路径,包含 PEM 编码文件,包含发送到 libcurl 的证书颁发机构。
示例
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;
身份验证
Azure 扩展有两种配置身份验证的方式。首选方式是使用 Secrets。
使用 Secret 进行身份验证
Azure 扩展有多个秘密提供程序可用
- 如果您需要为不同的存储账户定义不同的秘密,请使用
SCOPE
配置。请注意,SCOPE
需要末尾的斜杠(SCOPE 'azure://some_container/'
)。 - 如果您使用完全限定路径,则
ACCOUNT_NAME
属性是可选的。
CONFIG
提供程序
默认提供程序 CONFIG
(即用户配置)允许使用连接字符串或匿名方式访问存储账户。例如
CREATE SECRET secret1 (
TYPE azure,
CONNECTION_STRING 'value'
);
如果您不使用身份验证,您仍然需要指定存储账户名称。例如
CREATE SECRET secret2 (
TYPE azure,
PROVIDER config,
ACCOUNT_NAME 'storage_account_name'
);
默认的 PROVIDER
是 CONFIG
。
credential_chain
提供者
credential_chain
提供程序允许使用 Azure SDK 通过 Azure 凭据链自动获取凭据进行连接。默认情况下,使用 DefaultAzureCredential
链,它按照 Azure 文档中指定的顺序尝试凭据。例如
CREATE SECRET secret3 (
TYPE azure,
PROVIDER credential_chain,
ACCOUNT_NAME 'storage_account_name'
);
DuckDB 还允许使用 CHAIN
关键字指定特定的链。它接受以分号分隔的提供程序列表(a;b;c
),这些提供程序将按顺序尝试。例如
CREATE SECRET secret4 (
TYPE azure,
PROVIDER credential_chain,
CHAIN 'cli;env',
ACCOUNT_NAME 'storage_account_name'
);
可能的值如下:cli
;managed_identity
;env
;default
;
如果未提供明确的 CHAIN
,则默认值为 default
SERVICE_PRINCIPAL
提供程序
SERVICE_PRINCIPAL
提供程序允许使用 Azure 服务主体 (SPN) 进行连接。
使用秘密
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'
);
或使用证书
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'
);
配置代理
要在使用秘密时配置代理信息,您可以在秘密定义中添加 HTTP_PROXY
、PROXY_USER_NAME
和 PROXY_PASSWORD
。例如
CREATE SECRET secret5 (
TYPE azure,
CONNECTION_STRING 'value',
HTTP_PROXY 'https://:3128',
PROXY_USER_NAME 'john',
PROXY_PASSWORD 'doe'
);
- 使用秘密时,
HTTP_PROXY
环境变量仍将被尊重,除非您为其提供一个显式值。- 使用秘密时,将忽略“使用变量进行身份验证”会话的
SET
变量。- Azure
credential_chain
提供程序,实际令牌是在查询时获取的,而不是在创建秘密时获取的。
使用变量进行身份验证(已弃用)
SET variable_name = variable_value;
其中 variable_name
可以是以下之一
名称 | 描述 | 类型 | 默认值 |
---|---|---|---|
azure_storage_connection_string |
Azure 连接字符串,用于验证和配置 Azure 请求。 | 字符串 |
- |
azure_account_name |
Azure 账户名称,设置后,扩展将尝试自动检测凭据(如果传递了连接字符串则不使用)。 | 字符串 |
- |
azure_endpoint |
覆盖使用 Azure 凭据提供程序时的 Azure 端点。 | 字符串 |
blob.core.windows.net |
azure_credential_chain |
Azure 凭据提供程序的有序列表,以 ; 分隔的字符串格式。例如:'cli;managed_identity;env' 。请参阅credential_chain 提供程序部分中可能值的列表。如果传递了连接字符串则不使用。 |
字符串 |
- |
azure_http_proxy |
登录和执行 Azure 请求时使用的代理。 | 字符串 |
HTTP_PROXY 环境变量(如果已设置)。 |
azure_proxy_user_name |
如果需要,HTTP 代理用户名。 | 字符串 |
- |
azure_proxy_password |
如果需要,HTTP 代理密码。 | 字符串 |
- |
附加信息
日志记录
Azure 扩展依赖 Azure SDK 连接到 Azure Blob 存储,并支持将 SDK 日志打印到控制台。要控制日志级别,请设置 AZURE_LOG_LEVEL
环境变量。
例如,可以在 Python 中启用详细日志,如下所示
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'")
ADLS 和 Blob 存储之间的区别
尽管 ADLS 实现了与 Blob 存储类似的功能,但对于通配符,特别是使用(复杂)通配符模式时,使用 ADLS 端点有一些重要的性能优势。
为了演示,我们来看一个通配符如何分别使用 Blob 和 ADLS 端点在内部执行的示例。
使用以下文件系统
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
以下查询通过 Blob 端点执行
SELECT count(*)
FROM 'az://root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv';
它将执行以下步骤
- 列出所有前缀为
root/l_receipmonth=1997-
的文件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
- 使用请求的模式
root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv
过滤结果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
同时,相同的查询可以通过数据湖端点执行,如下所示
SELECT count(*)
FROM 'abfss://root/l_receipmonth=1997-*/l_shipmode=SHIP/*.csv';
这将执行以下步骤
- 列出
root/
中的所有目录root/l_receipmonth=1997-10
root/l_receipmonth=1997-11
root/l_receipmonth=1997-12
- 过滤并列出子目录:
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
- 过滤并列出子目录:
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
如您所见,由于 Blob 端点不支持目录的概念,过滤只能在列表之后执行,而 ADLS 端点将递归列出文件。特别是在分区/目录数量较高时,性能差异可能非常显著。