通过 Snowflake Horizon 目录使用外部引擎查询 Apache Iceberg™ 表¶
此预览版引入了通过 Snowflake Horizon 目录使用外部查询引擎查询 Snowflake 托管的 Apache Iceberg™ 表的支持。为了确保与外部引擎的互操作性,`_Apache Polaris™(孵化中)`<https://github.com/apache/polaris (https://github.com/apache/polaris)> 已集成到 Horizon 目录中。此外,Horizon 目录还公开了 Apache Iceberg™ REST APIs,它允许您使用外部查询引擎读取表。
要使用外部查询引擎查询 Snowflake 托管的 Iceberg 表,您可以使用此功能,而不是 将 Sguowflake 托管的 Iceberg 表与 Snowflake Open Catalog 同步。有关 Open Catalog 的更多信息,请参阅 Snowflake Open Catalog 概述。
通过 Horizon 目录将外部查询引擎连接到 Iceberg 表,您可以执行以下任务:
使用任何支持开放 Iceberg REST 协议的外部查询引擎(例如 Apache Spark™)查询这些表。
使用单个 Horizon 目录端点,查询新的或现有的 Snowflake 账户中任何现有和新的 Snowflake 托管的 Iceberg 表。
使用 Snowflake 中的现有用户、角色、策略和身份验证来查询表。
使用分发的凭据。
有关 Snowflake Horizon 目录的更多信息,请参阅 Snowflake Horizon 目录。
下图显示了外部查询引擎通过 Horizon 目录读取 Snowflake 托管的 Iceberg 表,以及 Snowflake 对这些表的读取和写入:
计费¶
Horizon Iceberg REST 目录 API 适用于所有 Snowflake 版本。
API 请求按每百万次调用 0.5 Credit 计费,并作为云服务进行收费。
对于跨区域数据访问,将适用 Snowflake 服务消耗表 中的标准跨区域数据出口费。
备注
在此功能正式发布之前,客户不会收到任何账单。
准备工作¶
检索包含要查询的 Iceberg 表的 Snowflake 的账户账户标识符。有关说明,请参阅 账户标识符。您可以在 将外部查询引擎连接到 Iceberg 表 时指定此标识符。
小技巧
要获取您的账户标识符,请使用 SQL,您可以运行以下命令:
SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME();
专用连接(可选)¶
为确保安全连接,建议在访问 Horizon Catalog 端点时,为您的 Snowflake 账户配置 入站 和 出站 专用连接。
备注
专用连接仅支持存储在 Amazon S3 或 Azure 存储 (ADLS) 中的由 Snowflake 管理的 Iceberg 表。
使用外部查询引擎查询 Iceberg 表的工作流程¶
要使用外部查询引擎查询 Iceberg 表,请完成以下步骤:
创建 Iceberg 表。
配置访问控制。
获取用于身份验证的访问令牌。
通过 Horizon 目录将外部查询引擎连接到 Iceberg 表。
查询 Iceberg 表。
第 1 步:创建 Iceberg 表¶
重要
如果您已经拥有要查询的 Snowflake 托管的 Iceberg 表,则可以跳过此步骤。
在此步骤中,您将创建 Snowflake 托管的 Iceberg 表,这些表使用 Snowflake 作为目录,从而支持通过外部查询引擎对这些表进行查询。有关说明,请参阅以下主题:
教程:创建第一个 Apache Iceberg™ 表:选择使用 时默认使用的角色和仓库。本教程展示了如何创建数据库、创建 Snowflake 托管的 Iceberg 表以及将数据加载到表中。
创建 Snowflake 托管的 Iceberg 表:Snowflake 托管的 Iceberg 表的创建示例代码。
第 2 步:配置访问控制¶
重要
通过 Horizon 目录端点访问 Iceberg 表时,不支持角色名称中包含连字符 (-) 的 Snowflake 角色。
如果您已经配置具备访问目标 Iceberg 表权限的角色,则可以跳过此步骤。
在此步骤中,您将为要使用外部查询引擎查询的 Snowflake 托管的 Iceberg 表配置访问控制。例如,您可以在 Snowflake 中设置以下角色:
DATA_ENGINEER 角色,该角色有权访问数据库中的所有架构和所有 Snowflake 托管的 Iceberg 表。
DATA_ANALYST 角色,该角色可以访问数据库中的一个架构,但只能访问该架构内的两个 Snowflake 托管的 Iceberg 表。
第 3 步:获取用于身份验证的访问令牌¶
在此步骤中,您将获得一个访问令牌,您必须使用该令牌对 Snowflake 账户的 Horizon 目录端点进行身份验证。您需要为配置为可以访问 Snowflake 托管的 Iceberg 表的每个用户(服务或人员)和角色获取访问令牌。例如,您需要为具有 DATA_ENGINEER 角色的用户获取一个访问令牌,并为具有另一个 DATA_ANALYST 角色的用户再获取一个访问令牌。
稍后,当您 通过 Horizon 目录将外部查询引擎连接到 Iceberg 表 时,需要指定该访问令牌。
您可以使用以下身份验证选项之一获取访问令牌:
外部 OAuth:如果您使用的是外部 OAuth,请为身份提供商生成访问令牌。有关说明,请参阅 External OAuth 概览。
备注
对于外部 OAuth,您还可以使用自动令牌刷新配置与引擎的连接,而不是指定访问令牌。
密钥对身份验证:如果您使用密钥对身份验证,且要获取访问令牌,您需要使用私钥签署 JSON 网络令牌 (JWT)。有关说明,请参阅 密钥对身份验证。
编程访问令牌 (PAT):如果您使用 PATs,则生成用于身份验证的 PAT。有关说明,请参阅 用于身份验证的编程访问令牌。
第 4 步:通过 Horizon 目录将外部查询引擎连接到 Iceberg 表¶
在此步骤中,您将通过 Horizon 目录将外部查询引擎连接到 Iceberg 表。此连接允许您使用外部查询引擎对表进行查询。
外部引擎使用 Snowflake 公开的 Apache Iceberg™ REST 端点。对于您的 Snowflake 账户,此端点采用以下格式:
https://<accountidentifier>.snowflakecomputing.cn/polaris/api/catalog
此步骤中的示例代码展示了如何在 Spark 中设置连接,示例代码则位于 PySpark。有关详细信息,请参阅以下主题:
使用外部 OAuth 或密钥对身份验证进行连接¶
使用以下示例代码将外部查询引擎连接到 Iceberg 表,方法是使用外部 OAuth 或密钥对身份验证:
# Snowflake Horizon Catalog Configuration, change as per your environment
CATALOG_URI = "https://<accountidentifier>.snowflakecomputing.cn/polaris/api/catalog"
HORIZON_SESSION_ROLE = f"session:role:<role>"
CATALOG_NAME = "<database_name>" #provide in UPPER CASE
# Cloud Service Provider Region Configuration (where the Iceberg data is stored)
REGION = "eastus2"
# Paste the External Oauth Access token that you generated in Snowflake here
ACCESS_TOKEN = "<your_access_token>"
# Iceberg Version
ICEBERG_VERSION = "1.9.1"
def create_spark_session():
"""Create and configure Spark session for Snowflake Iceberg access."""
spark = (
SparkSession.builder
.appName("SnowflakeIcebergReader")
.master("local[*]")
# JAR Dependencies for Iceberg and Azure
.config(
"spark.jars.packages",
f"org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:{ICEBERG_VERSION},"
f"org.apache.iceberg:iceberg-aws-bundle:{ICEBERG_VERSION}"
# for Azure storage, use the below package and comment above azure bundle
# f"org.apache.iceberg:iceberg-azure-bundle:{ICEBERG_VERSION}"
)
# Iceberg SQL Extensions
.config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
.config("spark.sql.defaultCatalog", CATALOG_NAME)
# Horizon REST Catalog Configuration
.config(f"spark.sql.catalog.{CATALOG_NAME}", "org.apache.iceberg.spark.SparkCatalog")
.config(f"spark.sql.catalog.{CATALOG_NAME}.type", "rest")
.config(f"spark.sql.catalog.{CATALOG_NAME}.uri", CATALOG_URI)
.config(f"spark.sql.catalog.{CATALOG_NAME}.warehouse", CATALOG_NAME)
.config(f"spark.sql.catalog.{CATALOG_NAME}.token", ACCESS_TOKEN)
.config(f"spark.sql.catalog.{CATALOG_NAME}.scope", HORIZON_SESSION_ROLE)
.config(f"spark.sql.catalog.{CATALOG_NAME}.client.region", REGION)
# Required for vended credentials
.config(f"spark.sql.catalog.{CATALOG_NAME}.header.X-Iceberg-Access-Delegation", "vended-credentials")
.config("spark.sql.iceberg.vectorization.enabled", "false")
.getOrCreate()
)
spark.sparkContext.setLogLevel("ERROR")
return spark
其中:
<accountidentifier>是包含要查询的 Iceberg 表的 Snowflake 账户的 Snowflake 账户标识符。要查找此标识符,请参阅 准备工作。<your_access_token>是您获得的访问令牌。要获取该令牌,请参阅 第 3 步:获取用于身份验证的访问令牌。备注
对于外部 OAuth,您还可以使用自动令牌刷新配置与引擎的连接,而不是指定访问令牌。
<database_name>是 Snowflake 账户中数据库的名称,该数据库包含您要查询的 Snowflake 托管的 Iceberg 表。备注
Spark 中的
.warehouse属性需要 Snowflake 数据库 名称,而不是 Snowflake 仓库名称。<role>是 Snowflake 中配置为对要查询的 Iceberg 表具有访问权限的角色。例如:DATA_ENGINEER。
重要
默认情况下,代码示例是针对存储在 Amazon S3 上的 Apache Iceberg™ 表进行设置的。如果您的 Iceberg 表存储在 Azure 存储 (ADLS) 中,请执行以下步骤:
注释以下行:
f"org.apache.iceberg:iceberg-aws-bundle:{ICEBERG_VERSION}"取消注释以下行:
# f"org.apache.iceberg:iceberg-azure-bundle:{ICEBERG_VERSION}"
使用编程访问令牌 (PAT) 进行连接¶
使用以下示例代码,通过编程访问令牌 (PAT) 将外部查询引擎连接到 Iceberg 表:
# Snowflake Horizon Catalog Configuration, change as per your environment
CATALOG_URI = "https://<accountidentifier>.snowflakecomputing.cn/polaris/api/catalog"
HORIZON_SESSION_ROLE = f"session:role:<role>"
CATALOG_NAME = "<database_name>" #provide in UPPER CASE
# Cloud Service Provider Region Configuration (where the Iceberg data is stored)
REGION = "eastus2"
# Paste the PAT you generated in Snowflake here
PAT_TOKEN = "<your_PAT_token>"
# Iceberg Version
ICEBERG_VERSION = "1.9.1"
def create_spark_session():
"""Create and configure Spark session for Snowflake Iceberg access."""
spark = (
SparkSession.builder
.appName("SnowflakeIcebergReader")
.master("local[*]")
# JAR Dependencies for Iceberg and Azure
.config(
"spark.jars.packages",
f"org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:{ICEBERG_VERSION},"
f"org.apache.iceberg:iceberg-aws-bundle:{ICEBERG_VERSION}"
# for Azure storage, use the below package and comment above azure bundle
# f"org.apache.iceberg:iceberg-azure-bundle:{ICEBERG_VERSION}"
)
# Iceberg SQL Extensions
.config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
.config("spark.sql.defaultCatalog", CATALOG_NAME)
# Horizon REST Catalog Configuration
.config(f"spark.sql.catalog.{CATALOG_NAME}", "org.apache.iceberg.spark.SparkCatalog")
.config(f"spark.sql.catalog.{CATALOG_NAME}.type", "rest")
.config(f"spark.sql.catalog.{CATALOG_NAME}.uri", CATALOG_URI)
.config(f"spark.sql.catalog.{CATALOG_NAME}.warehouse", CATALOG_NAME)
.config(f"spark.sql.catalog.{CATALOG_NAME}.credential", PAT_TOKEN)
.config(f"spark.sql.catalog.{CATALOG_NAME}.scope", HORIZON_SESSION_ROLE)
.config(f"spark.sql.catalog.{CATALOG_NAME}.client.region", REGION)
# Required for vended credentials
.config(f"spark.sql.catalog.{CATALOG_NAME}.header.X-Iceberg-Access-Delegation", "vended-credentials")
.config("spark.sql.iceberg.vectorization.enabled", "false")
.getOrCreate()
)
spark.sparkContext.setLogLevel("ERROR")
return spark
其中:
<accountidentifier>是包含要查询的 Iceberg 表的 Snowflake 账户的 Snowflake 账户标识符。要查找此标识符,请参阅 准备工作。<your_PAT_token>是您获取的 PAT。要获取该令牌,请参阅 第 3 步:获取用于身份验证的访问令牌。<role>是 Snowflake 中配置为对要查询的 Iceberg 表具有访问权限的角色。例如:DATA_ENGINEER。<database_name>是 Snowflake 账户中数据库的名称,该数据库包含您要查询的 Snowflake 托管的 Iceberg 表。备注
Spark 中的
.warehouse属性需要 Snowflake 数据库 名称,而不是 Snowflake 仓库名称。
重要
默认情况下,代码示例是针对存储在 Amazon S3 上的 Apache Iceberg™ 表进行设置的。如果您的 Iceberg 表存储在 Azure 存储 (ADLS) 中,请执行以下步骤:
注释以下行:
f"org.apache.iceberg:iceberg-aws-bundle:{ICEBERG_VERSION}"取消注释以下行:
# f"org.apache.iceberg:iceberg-azure-bundle:{ICEBERG_VERSION}"
第 5 步:查询 Iceberg 表¶
此步骤提供了使用 Apache Spark™ 查询 Iceberg 表的以下代码示例:
显示命名空间
使用命名空间
显示表
查询表
显示命名空间¶
spark.sql("show namespaces").show()
使用命名空间¶
spark.sql("use namespace <your_schema_name_in_snowflake>")
显示表¶
spark.sql("show tables").show()
查询表¶
spark.sql("use namespace spark_demo")
spark.sql("select * from <your_table_name_in_snowflake>").show()
使用外部查询引擎查询 Iceberg 表的注意事项¶
使用外部查询引擎查询 Iceberg 表时,请考虑以下事项:
对于 Snowflake 中的表:
仅支持 Snowflake 托管的 Iceberg 表。
不支持查询远程或外部托管的 Iceberg 表,包括 Delta Direct 和 Parquet Direct 表以及 Snowflake 原生表。
您可以查询,但不能写入 Iceberg 表。
仅 Iceberg 版本 2 或更早版本支持外部读取。
此功能仅支持存储在 Amazon S3、Google Cloud 或 Azure 上由 Snowflake 托管的 Iceberg 表,并适用于所有公共云区域。与 S3 兼容的非 AWS 尚不支持存储。
如果在表上定义了以下细粒度访问控制 (FGAC) 策略,则无法通过 Horizon Iceberg REST API 查询该 Iceberg 表:
行访问策略
列级安全性
通过 Horizon 目录端点访问 Iceberg 表时,不支持角色名称中包含连字符 (-) 的 Snowflake 角色。
不支持显式授予 Horizon 目录端点对存储账户的访问权限。我们建议使用专用连接,以确保从外部引擎到 Horizon 目录,以及从 Horizon 目录到存储账户的连接安全。