S3 API 支持
httpfs 扩展支持在使用 S3 API 的对象存储服务上读取/写入/globbing 文件。S3 提供了远程文件读写的标准 API(而早于 S3 的常规 http 服务器并无统一写 API)。Goose 遵循 S3 API,该 API 现已成为业界存储提供商的通用接口。
平台
httpfs 文件系统已在 AWS S3、Minio、Google Cloud 上测试。
其他实现 S3 API 的服务(如 Cloudflare R2)通常也可工作,但未必支持全部功能。
下表展示了 httpfs 各功能所需的 S3 API 能力。
| 功能 | 所需 S3 API 能力 |
|---|---|
| 公共文件读取 | HTTP Range requests |
| 私有文件读取 | Secret key 或 session token 认证 |
| 文件 glob | ListObjectsV2 |
| 文件写入 | Multipart upload |
配置与认证
配置和认证 S3 endpoints 的推荐方式是使用 secrets。支持多个 secret provider。
若要从已弃用 S3 API 方式迁移,请使用带 profile 的已定义 secret。 详见“基于 Profile 加载 Secret”。
config Provider
默认 provider 为 config(即用户配置)。通过手动提供 key 访问 S3 bucket。例如:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER config,
KEY_ID '⟨AKIAIOSFODNN7EXAMPLE⟩',
SECRET '⟨wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY⟩',
REGION '⟨us-east-1⟩'
);
提示:若出现 IO Error(
Connection error for HTTP HEAD),请显式配置 endpoint:ENDPOINT 's3.⟨your-region⟩.amazonaws.com'。
使用上述 secret 查询时,直接查询任意 s3:// 前缀文件即可:
SELECT *
FROM 's3://⟨your-bucket⟩/⟨your_file⟩.parquet';
credential_chain Provider
credential_chain provider 可借助 AWS SDK 机制自动获取凭据。例如,使用 AWS SDK 默认 provider:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER credential_chain
);
同样,使用该 secret 查询时直接查询任意 s3:// 前缀文件即可。
Goose 也支持通过 CHAIN 指定具体链路。该值为分号分隔的 provider 列表(a;b;c),会按顺序尝试。例如:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER credential_chain,
CHAIN 'env;config'
);
CHAIN 可选值如下:
credential_chain provider 也允许覆盖自动获取的配置。例如,先自动加载凭据,再覆盖 region:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER credential_chain,
CHAIN config,
REGION '⟨eu-west-1⟩'
);
基于 Profile 加载 Secret
若要基于某个 profile 加载凭据(该 profile 既非 AWS_PROFILE 环境变量指定的默认 profile,也非 AWS SDK 优先级规则下的默认 profile),请执行:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER credential_chain,
CHAIN config,
PROFILE '⟨my_profile⟩'
);
该方式等价于已弃用 S3 API中的 load_aws_credentials('⟨my_profile⟩') 方法。
S3 Secret 参数总览
下表为 config 与 credential_chain 两种 provider 都可使用的完整参数列表:
| 名称 | 说明 | Secret | 类型 | 默认值 |
|---|---|---|---|---|
ENDPOINT | Specify a custom S3 endpoint | S3, GCS, R2 | STRING | s3.amazonaws.com for S3, |
KEY_ID | The ID of the key to use | S3, GCS, R2 | STRING | - |
REGION | The region for which to authenticate (should match the region of the bucket to query) | S3, GCS, R2 | STRING | us-east-1 |
SECRET | The secret of the key to use | S3, GCS, R2 | STRING | - |
SESSION_TOKEN | Optionally, a session token can be passed to use temporary credentials | S3, GCS, R2 | STRING | - |
URL_COMPATIBILITY_MODE | Can help when URLs contain problematic characters | S3, GCS, R2 | BOOLEAN | true |
URL_STYLE | Either vhost or path | S3, GCS, R2 | STRING | vhost for S3, path for R2 and GCS |
USE_SSL | Whether to use HTTPS or HTTP | S3, GCS, R2 | BOOLEAN | true |
VERIFY_SSL | Whether to verify the SSL certificate of the server | S3, GCS, R2 | BOOLEAN | true |
ACCOUNT_ID | The R2 account ID to use for generating the endpoint URL | R2 | STRING | - |
KMS_KEY_ID | AWS KMS (Key Management Service) key for Server Side Encryption S3 | S3 | STRING | - |
REQUESTER_PAYS | Allows use of "requester pays" S3 buckets | S3 | BOOLEAN | false |
平台特定 Secret 类型
S3 Secrets
httpfs 扩展支持通过 KMS_KEY_ID 选项启用 S3 上基于 AWS Key Management Service (KMS) 的服务端加密:
CREATE OR REPLACE SECRET secret (
TYPE s3,
PROVIDER credential_chain,
CHAIN config,
REGION '⟨eu-west-1⟩',
KMS_KEY_ID 'arn:aws:kms:⟨region⟩:⟨account_id⟩:⟨key⟩/⟨key_id⟩',
SCOPE 's3://⟨bucket-sub-path⟩'
);
R2 Secrets
虽然 Cloudflare R2 使用常规 S3 API,但 Goose 提供了专用 Secret 类型 R2,以简化配置:
CREATE OR REPLACE SECRET secret (
TYPE r2,
KEY_ID '⟨AKIAIOSFODNN7EXAMPLE⟩',
SECRET '⟨wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY⟩',
ACCOUNT_ID '⟨my_account_id⟩'
);
注意新增的 ACCOUNT_ID,它用于自动生成正确 endpoint URL。R2 Secret 也可使用 CONFIG 与 credential_chain 两种 provider。
但由于 Goose 内部使用 AWS 客户端,使用 credential_chain 时会在标准 AWS 凭据位置(环境变量、凭据文件等)查找凭据。
因此,为确保 credential chain 正常工作,需要将 R2 凭据以 AWS 环境变量(AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY)提供。
最后,R2 secret 仅在 URL 以 r2:// 开头时生效,例如:
SELECT *
FROM read_parquet('r2://⟨some-file-that-uses-an-r2-secret⟩.parquet');
GCS Secrets
虽然 Goose 通过 S3 API 访问 Google Cloud Storage,但 Goose 提供了专用 Secret 类型 GCS 来简化配置:
CREATE OR REPLACE SECRET secret (
TYPE gcs,
KEY_ID '⟨my_hmac_access_id⟩',
SECRET '⟨my_hmac_secret_key⟩'
);
重要:KEY_ID 与 SECRET 必须是专为 Google Cloud Storage 互操作生成的 HMAC 密钥。这与常规 GCP service account key 或 access token 不同。可参考 Google Cloud 文档(管理 HMAC 密钥)创建。
请注意,上述 secret 会自动配置正确的 Google Cloud Storage endpoint。GCS Secret 也可使用 CONFIG 与 credential_chain 两种 provider。
但由于 Goose 内部使用 AWS 客户端,使用 credential_chain 时会在标准 AWS 凭据位置(环境变量、凭据文件等)查找凭据。
因此,为确保 credential chain 正常工作,需将 GCS HMAC 密钥以 AWS 环境变量(AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY)提供。
最后,GCS secret 仅在 URL 以 gcs:// 或 gs:// 开头时生效,例如:
SELECT *
FROM read_parquet('gcs://⟨some/file/that/uses/a/gcs/secret⟩.parquet');
读取
从 S3 读取文件可以非常简单:
SELECT *
FROM 's3://⟨your-bucket⟩/⟨filename⟩.⟨extension⟩';
部分读取
httpfs 扩展支持从 S3 bucket 进行部分读取。
读取多个文件
也支持读取多个文件,例如:
SELECT *
FROM read_parquet([
's3://⟨your-bucket⟩/⟨filename-1⟩.parquet',
's3://⟨your-bucket⟩/⟨filename-2⟩.parquet'
]);
Globbing
文件 globbing 通过 ListObjectsV2 API 实现,可使用类似文件系统的 glob 模式匹配多个文件,例如:
SELECT *
FROM read_parquet('s3://⟨your-bucket⟩/*.parquet');
该查询会匹配 bucket 根目录下所有 Parquet 扩展文件。
支持多种匹配能力,例如:* 匹配任意数量任意字符,? 匹配任意单字符,[0-9] 匹配范围内单字符:
SELECT count(*) FROM read_parquet('s3://⟨your-bucket⟩/folder*/100?/t[0-9].parquet');
使用 glob 时,一个实用选项是 filename。它会新增 filename 列,用于标识每一行来自哪个文件:
SELECT *
FROM read_parquet('s3://⟨your-bucket⟩/*.parquet', filename = true);
例如,结果可能如下:
| column_a | column_b | filename |
|---|---|---|
| 1 | examplevalue1 | s3://bucket-name/file1.parquet |
| 2 | examplevalue1 | s3://bucket-name/file2.parquet |
Hive 分区
Goose 还支持 Hive 分区方案,该能力在 HTTP(S) 与 S3 endpoint 下均可用。
写入
写入 S3 使用 multipart upload API。这使 Goose 可以稳定且高速上传文件。S3 写入同时支持 CSV 与 Parquet:
COPY table_name TO 's3://⟨your-bucket⟩/⟨filename⟩.⟨extension⟩';
向 S3 的分区写出同样支持:
COPY table TO 's3://⟨your-bucket⟩/partitioned' (
FORMAT parquet,
PARTITION_BY (⟨part_col_a⟩, ⟨part_col_b⟩)
);
系统会自动检查目标文件/目录是否已存在。当前检查策略较保守(在 S3 上会增加少量延迟)。若要禁用检查并强制写入,可添加 OVERWRITE_OR_IGNORE 标志:
COPY table TO 's3://⟨your-bucket⟩/partitioned' (
FORMAT parquet,
PARTITION_BY (⟨part_col_a⟩, ⟨part_col_b⟩),
OVERWRITE_OR_IGNORE true
);
写出文件命名形式如下:
s3://⟨your-bucket⟩/partitioned/part_col_a=⟨val⟩/part_col_b=⟨val⟩/data_⟨thread_number⟩.parquet
配置
S3 上传支持一些附加配置项,但默认值通常足以满足大多数场景。
| 名称 | 说明 |
|---|---|
s3_uploader_max_parts_per_file | Used for part size calculation, see AWS docs |
s3_uploader_max_filesize | Used for part size calculation, see AWS docs |
s3_uploader_thread_limit | Maximum number of uploader threads |