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&paramN=valueN]

  • user[:password]@account/database[?param1=value1&paramN=valueN]

  • user[:password]@host:port/database/schema?account=user_account[&param1=value1&paramN=valueN]

  • host:port/database/schema?account=user_account[&param1=value1&paramN=valueN]

请参阅官方 Snowflake 文档以获取有效的连接 URI,或参阅 Snowflake Go 驱动程序文档以手动构建 URI。请注意,从 Snowflake 的角度来看,arrow-adbc 被认为是 Snowflake Go 驱动程序,因为其实现是在底层使用的。

或者,无需提供完整的 URI,可以使用其他可用选项或 URI 与其他选项的组合来完全提供配置。如果提供了 URI,它将首先被解析,任何提供的显式选项将覆盖从 URI 解析的任何内容。

支持的功能

Snowflake 驱动程序通常支持 ADBC API 规范 1.0.0 中定义的特性,以及一些额外的自定义选项。

身份验证

Snowflake 需要启用某种形式的身份验证。默认情况下,它将尝试使用用户名/密码身份验证。用户名和密码可以在 URI 中提供,也可以通过 AdbcDatabaseusernamepassword 选项提供。

或者,可以指定和自定义其他类型的身份验证。有关所有选项的详细信息,请参阅下面的“客户端选项”。

SSO 身份验证

Snowflake 支持单点登录。如果您的帐户已配置 SSO,则可以通过在构建 AdbcDatabase 时设置以下选项来将其与 Snowflake 驱动程序一起使用

  • adbc.snowflake.sql.account:您的 Snowflake 帐户。(例如,如果您登录到 https://foobar.snowflakecomputing.com,那么您的帐户标识符是 foobar。)

  • adbc.snowflake.sql.auth_typeauth_ext_browser

  • username:您的用户名。(这可能应该是您的电子邮件,例如 jdoe@example.com。)

将出现一个新的浏览器标签页或窗口,您可以在其中继续登录。完成后,您将拥有一个完整的 ADBC 数据库/连接对象。一些用户报告需要其他配置选项,例如 adbc.snowflake.sql.regionadbc.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 Config 对象一一对应。

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

这应该是 httphttps

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:使用可编程访问令牌进行身份验证。

  • auth_wif:使用工作负载身份联合进行身份验证。

adbc.snowflake.sql.client_option.auth_token

如果使用 OAuth 或其他形式的身份验证,此选项是您显式指定用于连接的令牌的方式。

adbc.snowflake.sql.client_option.okta_url

如果使用 auth_okta,此选项是必需的,用于指定连接到 Okta 进行 SSO 身份验证的 Okta URL。

adbc.snowflake.sql.client_option.login_timeout

指定登录重试超时,不包括网络往返和读取 http 响应。值应按 此处 <https://pkg.go.dev/time#ParseDuration> 描述的格式设置,例如 300ms1.5s1m30s。即使接受负值,也将使用此类持续时间的绝对值。

adbc.snowflake.sql.client_option.request_timeout

指定请求重试超时,不包括网络往返和读取 http 响应。值应按 此处 <https://pkg.go.dev/time#ParseDuration> 描述的格式设置,例如 300ms1.5s1m30s。即使接受负值,也将使用此类持续时间的绝对值。

adbc.snowflake.sql.client_option.jwt_expire_timeout

JWT 将在此超时后过期。值应按 此处 <https://pkg.go.dev/time#ParseDuration> 描述的格式设置,例如 300ms1.5s1m30s。即使接受负值,也将使用此类持续时间的绝对值。

adbc.snowflake.sql.client_option.client_timeout

指定网络往返和读取 http 响应的超时。值应按 此处 <https://pkg.go.dev/time#ParseDuration> 描述的格式设置,例如 300ms1.5s1m30s。即使接受负值,也将使用此类持续时间的绝对值。

adbc.snowflake.sql.client_option.app_name

允许为连接指定 Snowflake 应用程序名称。

adbc.snowflake.sql.client_option.tls_skip_verify

禁用服务器 TLS 证书的验证。值应为 truefalse

adbc.snowflake.sql.client_option.ocsp_fail_open_mode

控制 OCSP 的故障开放模式。默认为 true。值应为 truefalse

adbc.snowflake.sql.client_option.keep_session_alive

即使连接关闭后,也允许会话持久存在。值应为 truefalse

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_telemetry

Snowflake 驱动程序允许遥测信息,可以通过将其设置为 true 来禁用。值应为 truefalse

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 列将作为 Decimal128 类型的 Arrow 列返回,使用 NUMBER 类型的精度和比例。当为 false 时,比例为 0 的 NUMBER 列将作为 Int64 类型的 Arrow 列返回,非零比例的列将作为 Float64 类型的 Arrow 列返回。默认值为 true

adbc.snowflake.sql.client_option.max_timestamp_precision

控制纳秒精度时间戳值的行为。原生 Go 行为是当年份早于 1677 年或晚于 2262 年时,这些值将溢出到不可预测的值。此选项可以控制 timestamp_ltztimestamp_ntztimestamp_tz 类型的行为。有效值为 - nanoseconds:对纳秒使用默认行为。- nanoseconds_error_on_overflow:当值将溢出时抛出错误,以强制数据完整性。- microseconds:将最大时间戳精度限制为微秒,这对所有值都是安全的。

元数据

调用 AdbcConnectionGetTableSchema() 时,返回的 Arrow 模式将包含每个字段的元数据

DATA_TYPE

这将是一个包含此列原始 Snowflake 数据类型的字符串

PRIMARY_KEY

这将是 YN,表示该列是否为主键。

此外,查询结果流中的模式将包含每个字段的以下元数据键

logicalType

此列的 Snowflake 逻辑类型。将是 fixedrealtextdatevarianttimestamp_ltztimestamp_ntztimestamp_tzobjectarraybinarytimeboolean 之一。

精度

一个整数,表示字段的 Snowflake 精度。

精度

一个整数,表示此字段中值的 Snowflake 比例。

charLength

如果为文本字段,这将等同于 VARCHAR(#) 参数 #

byteLength

将包含从 Snowflake 返回的原始数据长度(以字节为单位),而不考虑 Arrow 中字段的类型。

类型支持

由于 Snowflake 类型不一定与 Arrow 类型一一对应,因此在请求数据时应注意以下事项。所有指示的转换都旨在确保记录批次流的一致性。

Snowflake 类型

Arrow 类型

备注

整数类型

number(38, 0)

Snowflake 中的所有整数类型都存储为数字,既不能指定精度也不能指定比例。

浮点/双精度

float64

Snowflake 不区分浮点或双精度。两者都是 64 位值。

十进制/数值

数值

Snowflake 将遵守 Arrow 类型的精度/比例。有关此行为的例外情况,请参阅 adbc.snowflake.sql.client_option.use_high_precision

时间

time64[ns]

对于摄取,也可以使用 time32。

日期

date32

对于摄取,也可以使用 date64。

timestamp_ltz
timestamp_ntz
timestamp_tz

timestamp[ns]

将使用本地时区,但 timestamp_ntz 除外,它不是一个瞬间。在这种情况下,类型中将不存在时区。物理值将进行 UTC 规范化。

变体
对象
数组

string

Snowflake 不提供有关嵌套类型的信息。值将以类似于 JSON 的格式以字符串形式返回,可以解析。Arrow 类型将包含一个元数据键 logicalType,其中包含 Snowflake 字段类型。Arrow 结构和映射类型在摄取时将存储为对象。列表类型将存储为数组。

地理
几何

string

目前没有这些类型的规范 Arrow(扩展)类型,因此它们将作为 Snowflake 提供的字符串值返回。