跳到主要内容

S3 API 支持

httpfs 扩展支持在使用 S3 API 的对象存储服务上读取/写入/globbing 文件。S3 提供了远程文件读写的标准 API(而早于 S3 的常规 http 服务器并无统一写 API)。Goose 遵循 S3 API,该 API 现已成为业界存储提供商的通用接口。

平台

httpfs 文件系统已在 AWS S3MinioGoogle Cloud 上测试。 其他实现 S3 API 的服务(如 Cloudflare R2)通常也可工作,但未必支持全部功能。

下表展示了 httpfs 各功能所需的 S3 API 能力。

功能所需 S3 API 能力
公共文件读取HTTP Range requests
私有文件读取Secret key 或 session token 认证
文件 globListObjectsV2
文件写入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 参数总览

下表为 configcredential_chain 两种 provider 都可使用的完整参数列表:

名称说明Secret类型默认值
ENDPOINTSpecify a custom S3 endpointS3, GCS, R2STRINGs3.amazonaws.com for S3,
KEY_IDThe ID of the key to useS3, GCS, R2STRING-
REGIONThe region for which to authenticate (should match the region of the bucket to query)S3, GCS, R2STRINGus-east-1
SECRETThe secret of the key to useS3, GCS, R2STRING-
SESSION_TOKENOptionally, a session token can be passed to use temporary credentialsS3, GCS, R2STRING-
URL_COMPATIBILITY_MODECan help when URLs contain problematic charactersS3, GCS, R2BOOLEANtrue
URL_STYLEEither vhost or pathS3, GCS, R2STRINGvhost for S3, path for R2 and GCS
USE_SSLWhether to use HTTPS or HTTPS3, GCS, R2BOOLEANtrue
VERIFY_SSLWhether to verify the SSL certificate of the serverS3, GCS, R2BOOLEANtrue
ACCOUNT_IDThe R2 account ID to use for generating the endpoint URLR2STRING-
KMS_KEY_IDAWS KMS (Key Management Service) key for Server Side Encryption S3S3STRING-
REQUESTER_PAYSAllows use of "requester pays" S3 bucketsS3BOOLEANfalse

平台特定 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 也可使用 CONFIGcredential_chain 两种 provider。 但由于 Goose 内部使用 AWS 客户端,使用 credential_chain 时会在标准 AWS 凭据位置(环境变量、凭据文件等)查找凭据。 因此,为确保 credential chain 正常工作,需要将 R2 凭据以 AWS 环境变量(AWS_ACCESS_KEY_IDAWS_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_IDSECRET 必须是专为 Google Cloud Storage 互操作生成的 HMAC 密钥。这与常规 GCP service account key 或 access token 不同。可参考 Google Cloud 文档(管理 HMAC 密钥)创建。

请注意,上述 secret 会自动配置正确的 Google Cloud Storage endpoint。GCS Secret 也可使用 CONFIGcredential_chain 两种 provider。 但由于 Goose 内部使用 AWS 客户端,使用 credential_chain 时会在标准 AWS 凭据位置(环境变量、凭据文件等)查找凭据。 因此,为确保 credential chain 正常工作,需将 GCS HMAC 密钥以 AWS 环境变量(AWS_ACCESS_KEY_IDAWS_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_acolumn_bfilename
1examplevalue1s3://bucket-name/file1.parquet
2examplevalue1s3://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_fileUsed for part size calculation, see AWS docs
s3_uploader_max_filesizeUsed for part size calculation, see AWS docs
s3_uploader_thread_limitMaximum number of uploader threads