Snowflake 驱动程序¶
语言: Go 状态: 稳定
Snowflake 驱动程序提供对 Snowflake 数据库仓库的访问。
安装¶
通过 NuGet 安装 Apache.Arrow.Adbc.Drivers.Interop.Snowflake
dotnet package add Apache.Arrow.Adbc.Drivers.Interop.Snowflake
通过 conda-forge 安装 libadbc-driver-snowflake
mamba install libadbc-driver-snowflake
通过 Go 安装 github.com/apache/arrow-adbc/go/adbc/driver/snowflake
go get github.com/apache/arrow-adbc/go/adbc/driver/snowflake
通过 conda-forge 安装 adbc-driver-snowflake
mamba install adbc-driver-snowflake
通过 PyPI 安装 adbc-driver-snowflake
pip install adbc-driver-snowflake
通过 R-multiverse 安装 adbcsnowflake
install.packages("adbcsnowflake", repos = "https://community.r-multiverse.org")
通过 crates.io 安装 adbc_snowflake
cargo add adbc_snowflake
此外,该驱动程序可以通过驱动程序管理器从 C/C++、C#、GLib、Go、R、Ruby 和 Rust 使用。
用法¶
要连接到 Snowflake 数据库,您可以在构建 AdbcDatabase 时提供“uri”参数。
#include "arrow-adbc/adbc.h"
// Ignoring error handling
struct AdbcDatabase database;
AdbcDatabaseNew(&database, nullptr);
AdbcDatabaseSetOption(&database, "driver", "adbc_driver_snowflake", nullptr);
AdbcDatabaseSetOption(&database, "uri", "<snowflake uri>", nullptr);
AdbcDatabaseInit(&database, nullptr);
import adbc_driver_snowflake.dbapi
with adbc_driver_snowflake.dbapi.connect("<snowflake uri>") as conn:
pass
library(adbcdrivermanager)
# Use the driver manager to connect to a database
uri <- Sys.getenv("ADBC_SNOWFLAKE_TEST_URI")
db <- adbc_database_init(adbcsnowflake::adbcsnowflake(), uri = uri)
con <- adbc_connection_init(db)
import (
"context"
"github.com/apache/arrow-adbc/go/adbc"
"github.com/apache/arrow-adbc/go/adbc/driver/snowflake"
)
func main() {
var drv snowflake.Driver
db, err := drv.NewDatabase(map[string]string{
adbc.OptionKeyURI: "<snowflake uri>",
})
if err != nil {
// handle error
}
defer db.Close()
cnxn, err := db.Open(context.Background())
if err != nil {
// handle error
}
defer cnxn.Close()
}
URI 格式¶
Snowflake URI 应采用以下格式之一
user[:password]@account/database/schema[?param1=value1¶mN=valueN]user[:password]@account/database[?param1=value1¶mN=valueN]user[:password]@host:port/database/schema?account=user_account[¶m1=value1¶mN=valueN]host:port/database/schema?account=user_account[¶m1=value1¶mN=valueN]
请参考官方 Snowflake 文档以获取有效的连接 URI,或参考 Snowflake Go 驱动程序文档来手动构建 URI。请注意,在 Snowflake 上下文中,arrow-adbc 被视为 Snowflake Go 驱动程序,因为该实现是在底层使用的。
或者,不提供完整的 URI,也可以完全使用其他可用选项,或 URI 与其他选项的组合来提供配置。如果提供了 URI,它将首先被解析,任何明确提供的选项将覆盖从 URI 解析出的任何内容。
支持的功能¶
Snowflake 驱动程序通常支持 ADBC API 规范 1.0.0 中定义的特性,以及一些额外的自定义选项。
身份验证¶
Snowflake 需要启用某种形式的身份验证。默认情况下,它将尝试使用用户名/密码身份验证。用户名和密码可以在 URI 中提供,或者通过 AdbcDatabase 的 username 和 password 选项提供。
或者,可以指定并自定义其他类型的身份验证。有关所有选项的详细信息,请参阅下方的“客户端选项”。
SSO 身份验证¶
Snowflake 支持 单点登录 (SSO)。如果您的账户已配置 SSO,则可以在构建 AdbcDatabase 时设置以下选项来使用它:
adbc.snowflake.sql.account: 您的 Snowflake 账户。(例如,如果您登录到https://foobar.snowflakecomputing.com,那么您的账户标识符就是foobar。)adbc.snowflake.sql.auth_type:auth_ext_browser。username: 您的用户名。(这很可能是您的电子邮件地址,例如jdoe@example.com。)
此时应弹出一个新的浏览器标签页或窗口,您可以在其中继续登录。完成后,您将拥有一个完整的 ADBC 数据库/连接对象。一些用户报告需要其他配置选项,例如 adbc.snowflake.sql.region 和 adbc.snowflake.sql.uri.*(列表见下文)。
import adbc_driver_snowflake.dbapi
# This will open a new browser tab, and block until you log in.
adbc_driver_snowflake.dbapi.connect(db_kwargs={
"adbc.snowflake.sql.account": "foobar",
"adbc.snowflake.sql.auth_type": "auth_ext_browser",
"username": "jdoe@example.com",
})
library(adbcdrivermanager)
db <- adbc_database_init(
adbcsnowflake::adbcsnowflake(),
adbc.snowflake.sql.account = 'foobar',
adbc.snowflake.sql.auth_type = 'auth_ext_browser'
username = 'jdoe@example.com',
)
# This will open a new browser tab, and block until you log in.
con <- adbc_connection_init(db)
import (
"context"
"github.com/apache/arrow-adbc/go/adbc"
"github.com/apache/arrow-adbc/go/adbc/driver/snowflake"
)
func main() {
var drv snowflake.Driver
db, err := drv.NewDatabase(map[string]string{
snowflake.OptionAccount: "foobar",
snowflake.OptionAuthType: snowflake.OptionValueAuthExternalBrowser,
adbc.OptionKeyUsername: "jdoe@example.com",
})
if err != nil {
// handle error
}
defer db.Close()
cnxn, err := db.Open(context.Background())
if err != nil {
// handle error
}
defer cnxn.Close()
}
批量摄取¶
支持批量导入。Arrow 类型到 Snowflake 类型的映射如下所示。
批量导入通过将 Arrow 数据写入 Parquet 文件并(通过 PUT)上传到临时内部阶段来实现。执行一个或多个 COPY 查询以将数据加载到目标表中。
为了使驱动程序利用此临时阶段,用户必须在架构上拥有 CREATE STAGE <https://docs.snowflake.com/en/sql-reference/sql/create-stage> 权限。此外,必须设置会话的当前数据库和架构。如果未设置这些,驱动程序执行的 CREATE TEMPORARY STAGE 命令可能会失败,并出现以下错误
CREATE TEMPORARY STAGE ADBC$BIND FILE_FORMAT = (TYPE = PARQUET USE_LOGICAL_TYPE = TRUE BINARY_AS_TEXT = FALSE)
CANNOT perform CREATE STAGE. This session does not have a current schema. Call 'USE SCHEMA' or use a qualified name.
以下非正式基准测试展示了使用默认导入设置时的预期性能
Running on GCP e2-standard-4 (4 vCPU, 16GB RAM)
Snowflake warehouse size M, same GCP region as Snowflake account
Default ingestion settings
TPC-H Lineitem (16 Columns):
Scale Factor 1 (6M Rows): 9.5s
Scale Factor 10 (60M Rows): 45s
对于许多实际配置,导入的默认设置应该是平衡的。如果需要,可以通过 AdbcStatement 对象上的以下选项来调整性能和资源使用
adbc.snowflake.statement.ingest_writer_concurrency并行写入的 Parquet 文件数量。默认值会根据检测到的逻辑核心数尝试最大化工作线程,但在受限环境中运行可能需要调整。如果设置为 0,则使用默认值。不能为负数。
adbc.snowflake.statement.ingest_upload_concurrency并行上传的 Parquet 文件数量。更高的并发性可以平滑 TCP 拥塞并有助于利用可用的网络带宽,但会增加内存占用。默认值为 8。如果设置为 0,则使用默认值。不能为负数。
adbc.snowflake.statement.ingest_copy_concurrency同时运行的最大 COPY 操作数。通过在文件仍在上传时执行 COPY 查询,可以优化批量导入性能。Snowflake 的 COPY 速度随仓库大小而扩展,因此较小的仓库可能受益于将此值设置得更高,以确保长时间运行的 COPY 查询不会阻止新上传的文件被加载。默认值为 4。如果设置为 0,将没有限制,而是会为每个上传的文件执行一个新的 COPY INTO 查询。不能为负数。
adbc.snowflake.statement.ingest_target_file_size导入过程中写入的 Parquet 文件的近似大小。实际大小会略大一些,具体取决于页脚/元数据的大小。默认值为 10 MB。如果设置为 0,则文件大小没有限制。不能为负数。
分区结果集¶
目前不支持分区结果集。
性能¶
查询 Snowflake 数据时,结果可能从多个端点并行获取。每个端点排队处理的批次数量有限,尽管数据始终按端点顺序返回给客户端。
要管理结果获取的性能,有两个选项可以控制缓冲和并发行为。这些选项只能在 AdbcStatement 对象上设置
adbc.rpc.result_queue_size记录读取器中排队的批次数量。默认为 200。必须是大于 0 的整数。
adbc.snowflake.rpc.prefetch_concurrency一次从 Snowflake 获取的并发流数量。默认为 10。必须是大于 0 的整数。
事务¶
支持事务。请记住,如果运行任何 DDL 语句(例如 CREATE TABLE),Snowflake 事务将隐式提交。
客户端选项¶
用于创建 Snowflake 数据库连接的选项可以自定义。这些选项与 Snowflake 配置对象一一对应。
adbc.snowflake.sql.db此会话默认使用的数据库。
adbc.snowflake.sql.schema此会话默认使用的架构。
adbc.snowflake.sql.warehouse此会话默认使用的仓库。
adbc.snowflake.sql.role用于身份验证的角色。
adbc.snowflake.sql.region用于构建连接 URI 的 Snowflake 区域。
adbc.snowflake.sql.account用于身份验证和构建连接 URI 的 Snowflake 账户。
adbc.snowflake.sql.uri.protocol应为 http 或 https。
adbc.snowflake.sql.uri.port用于构建连接 URI 的端口。
adbc.snowflake.sql.uri.host用于构建连接 URL 的明确主机名。
adbc.snowflake.sql.auth_type允许指定替代的身份验证类型,允许的值为:
auth_snowflake: 常规用户名/密码身份验证(这是默认设置)auth_oauth: 使用 OAuth 身份验证进行 Snowflake 连接。auth_ext_browser: 使用外部浏览器访问联邦身份系统 (FED) 并执行 SSO 身份验证。auth_okta: 使用本地 Okta URL 通过 Okta 执行 SSO 身份验证auth_jwt: 使用提供的 JWT 执行身份验证。auth_mfa: 使用用户名和密码并结合多因素身份验证 (MFA)。auth_pat: 使用程序访问令牌 (PAT) 进行身份验证。auth_wif: 使用工作负载身份联合 (Workload Identity Federation) 进行身份验证。
adbc.snowflake.sql.client_option.auth_token如果使用 OAuth 或其他形式的身份验证,此选项用于明确指定用于连接的令牌。
adbc.snowflake.sql.client_option.okta_url如果使用
auth_okta,则必须使用此选项来指定用于 SSO 身份验证的 Okta URL。adbc.snowflake.sql.client_option.login_timeout指定登录重试超时时间,不包括网络往返和读取 HTTP 响应的时间。值应按此处 <https://pkg.go.dev/time#ParseDuration> 所述格式化,例如
300ms、1.5s或1m30s。即使接受负值,也会使用此类持续时间的绝对值。adbc.snowflake.sql.client_option.request_timeout指定请求重试超时时间,不包括网络往返和读取 HTTP 响应的时间。值应按此处 <https://pkg.go.dev/time#ParseDuration> 所述格式化,例如
300ms、1.5s或1m30s。即使接受负值,也会使用此类持续时间的绝对值。adbc.snowflake.sql.client_option.jwt_expire_timeoutJWT 将在此超时后过期。值应按此处 <https://pkg.go.dev/time#ParseDuration> 所述格式化,例如
300ms、1.5s或1m30s。即使接受负值,也会使用此类持续时间的绝对值。adbc.snowflake.sql.client_option.client_timeout指定网络往返和读取 HTTP 响应的超时时间。值应按此处 <https://pkg.go.dev/time#ParseDuration> 所述格式化,例如
300ms、1.5s或1m30s。即使接受负值,也会使用此类持续时间的绝对值。adbc.snowflake.sql.client_option.app_name允许为 Snowflake 连接指定应用程序名称。
adbc.snowflake.sql.client_option.tls_skip_verify禁用服务器 TLS 证书的验证。值应为
true或false。adbc.snowflake.sql.client_option.ocsp_fail_open_mode控制 OCSP 的故障开放 (fail open) 模式。默认为
true。值应为true或false。adbc.snowflake.sql.client_option.keep_session_alive即使在连接关闭后也允许会话持久存在。值应为
true或false。adbc.snowflake.sql.client_option.jwt_private_key指定用于签署 JWT 以进行身份验证的 RSA 私钥。这应该是包含 PKCS1 私钥的文件的路径,供读取和解析。通常以类型为“RSA PRIVATE KEY”的 PEM 块编码。
adbc.snowflake.sql.client_option.jwt_private_key_pkcs8_value解析加密或未加密的 PKCS #8 私钥,无需从文件系统读取它。如果使用加密的,则需要
adbc.snowflake.sql.client_option.jwt_private_key_pkcs8_password值并用于解密。adbc.snowflake.sql.client_option.jwt_private_key_pkcs8_password传递加密的 PKCS #8 值时使用的密码。
adbc.snowflake.sql.client_option.disable_telemetrySnowflake 驱动程序允许遥测信息,可以通过将其设置为
true来禁用。值应为true或false。adbc.snowflake.sql.client_option.config_file指定客户端配置 JSON 文件的位置。有关更多详细信息,请参阅 [Snowflake Go 文档](https://github.com/snowflakedb/gosnowflake/blob/a26ac8a1b9a0dda854ac5db9c2c145f79d5ac4c0/doc.go#L130)。
adbc.snowflake.sql.client_option.tracing设置日志级别
adbc.snowflake.sql.client_option.cache_mfa_token当为
true时,MFA 令牌缓存在凭据管理器中。在 Windows/OSX 上默认为true,在 Linux 上默认为false。adbc.snowflake.sql.client_option.store_temp_creds当为
true时,ID 令牌缓存在凭据管理器中。在 Windows/OSX 上默认为true,在 Linux 上默认为false。adbc.snowflake.sql.client_option.identity_provider当使用
auth_wif进行工作负载身份联合身份验证时,必须将其设置为相应的身份提供程序。adbc.snowflake.sql.client_option.use_high_precision当为
true时,具有NUMBER类型的定点 Snowflake 列将作为使用NUMBER类型精度和小数位数的Decimal128类型 Arrow 列返回。当为false时,小数位数为 0 的NUMBER列将作为Int64类型的 Arrow 列返回,非零小数位数的列将作为Float64类型的 Arrow 列返回。默认值为true。adbc.snowflake.sql.client_option.max_timestamp_precision控制纳秒精度时间戳值的行为。原生 Go 行为是,当年份早于 1677 年或晚于 2262 年时,这些值会溢出为不可预测的值。此选项可以控制 timestamp_ltz、timestamp_ntz 和 timestamp_tz 类型的行为。有效值为: -
nanoseconds:使用纳秒的默认行为。 -nanoseconds_error_on_overflow:当值溢出时抛出错误,以强制数据完整性。 -microseconds:将最大时间戳精度限制为微秒,这对所有值都是安全的。
元数据¶
调用 AdbcConnectionGetTableSchema() 时,返回的 Arrow Schema 将包含每个字段的元数据
DATA_TYPE这是一个包含此列原始 Snowflake 数据类型的字符串
PRIMARY_KEY这将是
Y或N,用于指示列是否为主键。
此外,查询结果流上的模式将在每个字段上包含以下元数据键
logicalType此列的 Snowflake 逻辑类型。将是
fixed、real、text、date、variant、timestamp_ltz、timestamp_ntz、timestamp_tz、object、array、binary、time、boolean之一。精度表示字段 Snowflake 精度的一个整数。
精度表示此字段中值的小数位数的一个整数。
charLength如果是文本字段,这将等同于
VARCHAR(#)参数#。byteLength将包含从 Snowflake 返回的原始数据的长度(以字节为单位),无论该字段在 Arrow 中的类型如何。
类型支持¶
由于 Snowflake 类型不一定与 Arrow 类型一一对应,因此在请求数据时应预期以下情况。所指出的任何转换都是为了确保记录批次流的一致性。
Snowflake 类型 |
Arrow 类型 |
备注 |
|---|---|---|
整数类型 |
number(38, 0) |
Snowflake 中的所有整数类型都存储为数字,既不能指定精度也不能指定小数位数。 |
float/double |
float64 |
Snowflake 不区分 float 或 double。两者都是 64 位值。 |
decimal/numeric |
numeric |
Snowflake 将遵循 Arrow 类型的精度/小数位数。有关此行为的例外情况,请参阅 |
time |
time64[ns] |
对于导入,也可以使用 time32。 |
date |
date32 |
对于导入,也可以使用 date64。 |
timestamp_ltz
timestamp_ntz
timestamp_tz
|
timestamp[ns] |
将使用本地时区,但 timestamp_ntz 除外,它不是一个瞬间。在这种情况下,类型中不会存在时区。物理值将被标准化为 UTC。 |
variant
object
数组
|
string |
Snowflake 不提供有关嵌套类型的信息。值将是类似于 JSON 格式的字符串,可以被解析。Arrow 类型将包含一个元数据键 |
geography
geometry
|
string |
目前没有这些类型的规范 Arrow (扩展) 类型,因此它们将作为 Snowflake 提供的字符串值返回。 |