自动刷新 Azure Blob 存储的外部表

本主题说明如何使用 Azure 容器的 Microsoft Azure 事件网格 (https://azure.microsoft.com/en-us/services/event-grid/) 通知自动创建外部表和刷新外部表元数据。此操作会将元数据与外部暂存区和路径中的最新一组关联文件同步,即:

  • 路径中的新文件将添加到表元数据中。

  • 对路径中文件的更改将在表元数据中更新。

  • 路径中不再存在的文件将从表元数据中移除。

Snowflake 支持以下类型的 Blob 存储账户:

  • Blob 存储

  • Data Lake Storage Gen2

  • General-purpose v2

请注意,只有 Microsoft.Storage.BlobCreatedMicrosoft.Storage.BlobDeleted 事件才会触发外部表元数据的刷新。向 Blob 存储添加新对象会触发这些事件。重命名目录或对象不会触发这些事件。 Snowflake 建议您仅发送外部表支持的事件,以降低成本、事件干扰和延迟。

Snowflake 支持以下 Microsoft.Storage.BlobCreated APIs:

  • CopyBlob

  • PutBlob

  • PutBlockList

  • FlushWithClose

  • SftpCommit

Snowflake 支持以下 Microsoft.Storage.BlobDeleted APIs:

  • DeleteBlob

  • DeleteFile

  • SftpRemove

对于 Data Lake Storage Gen2 存储账户,当客户端使用 CreateFileFlushWithClose 操作时会触发 Microsoft.Storage.BlobCreated 事件。如果使用 SSH 文件传输协议 (SFTP),则使用 SftpCreateSftpCommit 操作触发 Microsoft.Storage.BlobCreated 事件。CreateFileSftpCreate API 不会单独指示存储账户中的文件提交。如果未发送 FlushWithCloseSftpCommit 消息,则 Snowflake 不会刷新外部表元数据。

备注

要完成本主题中描述的任务,必须使用对架构具有 CREATE STAGE 和 CREATE EXTERNAL TABLE 权限的角色。

此外,您还必须具有 Microsoft Azure 的管理权限。如果您不是 Azure 管理员,请要求 Azure 管理员完成 第 1 步:配置事件网格订阅 中的步骤。

必须先创建通知集成,然后才能自动刷新 Azure Blob 存储的外部表。

Snowflake 仅支持 Azure 事件网格事件架构 (https://learn.microsoft.com/en-us/azure/event-grid/event-schema);不支持 Azure 事件网格 CloudEvents 架构 (https://learn.microsoft.com/en-us/azure/event-grid/cloud-event-schema)。

云平台支持

托管在 Microsoft Azure (Azure) 上的 Snowflake 账户支持使用 Azure 事件网格消息触发外部元数据的自动刷新。

配置对 Cloud Storage 的安全访问

备注

如果您已配置对存储数据文件的 Azure Blob 存储容器的安全访问,则可以跳过此部分。

本部分介绍如何配置 Snowflake 存储集成对象,以将云存储的身份验证责任委托给 Snowflake Identity and Access Management (IAM) 实体。

备注

我们强烈建议使用此选项,这样可以避免在访问云存储时提供 IAM 凭据。有关其他存储访问选项,请参阅 配置 Azure 容器以加载数据

本部分将描述如何使用存储集成来允许 Snowflake 从外部 (Azure) 暂存区中引用的 Azure 容器读取数据,并向其中写入数据。集成是已命名的第一类 Snowflake 对象,无需传递显式云提供商凭据(如密钥或访问令牌)。集成对象会存储称为 应用程序注册 的 Azure Identity and Access Management (IAM) 用户 ID。您组织中的管理员在 Azure 账户中授予此应用程序必要的权限。

集成还必须指定容器(和可选路径),以限制用户在创建使用集成的外部暂存区时可以指定的位置。

备注

需要具有在 Azure 中拥有管理存储账户的权限,才能完成本部分中的说明。如果您不是 Azure 管理员,请让 Azure 管理员执行这些任务。

本部分内容:

第 1 步:在 Snowflake 中创建云存储集成

使用 CREATE STORAGE INTEGRATION 命令创建存储集成。存储集成是一个 Snowflake 对象,它存储为 Azure 云存储生成的服务主体,以及一组可选的允许或阻止的存储位置(即容器)。组织中的云提供商管理员会将存储位置的权限授予生成的服务主体。此选项可让用户在创建暂存区或加载数据时无需提供凭据。

单个存储集成可以支持多个外部(如 Azure)暂存区。暂存区定义中的 URL 必须与为 STORAGE_ALLOWED_LOCATIONS 参数指定的 Azure 容器(和可选路径)一致。

备注

只有账户管理员(具有 ACCOUNTADMIN 角色的用户)或具有全局 CREATE INTEGRATION 权限的角色才能执行此 SQL 命令。

CREATE STORAGE INTEGRATION <integration_name>
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'AZURE'
  ENABLED = TRUE
  AZURE_TENANT_ID = '<tenant_id>'
  STORAGE_ALLOWED_LOCATIONS = ('azure://<account>.blob.core.windows.net/<container>/<path>/', 'azure://<account>.blob.core.windows.net/<container>/<path>/')
  [ STORAGE_BLOCKED_LOCATIONS = ('azure://<account>.blob.core.windows.net/<container>/<path>/', 'azure://<account>.blob.core.windows.net/<container>/<path>/') ]
Copy

其中:

  • integration_name 是新集成的名称。

  • tenant_id 是允许和阻止的存储账户所属的 Office 365 租户的 ID。存储集成只能对一个租户进行身份验证,因此允许和阻止的存储位置必须引用同属于此租户的存储账户。

    要查找租户 ID,请登录 Azure 门户并点击 Azure Active Directory » Properties。租户 ID 将显示在 Tenant ID 字段中。

  • container 是存储数据文件的 Azure 容器的名称(例如 mycontainer)。STORAGE_ALLOWED_LOCATIONS 和 STORAGE_BLOCKED_LOCATIONS 参数分别允许或阻止在创建或修改引用此集成的暂存区时访问这些容器。

  • path 是一个可选路径,可用于提供对容器中逻辑目录的精细控制。

以下示例创建一个集成,该集成明确限制使用该集成的外部暂存区只能引用两个容器和路径中的任意一个。在后面的步骤中,我们将创建一个外部暂存区,并引用这些容器和路径之一。使用此集成的多个外部暂存区可以引用受允许的容器和路径:

CREATE STORAGE INTEGRATION azure_int
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'AZURE'
  ENABLED = TRUE
  AZURE_TENANT_ID = 'a123b4c5-1234-123a-a12b-1a23b45678c9'
  STORAGE_ALLOWED_LOCATIONS = ('azure://myaccount.blob.core.windows.net/mycontainer1/mypath1/', 'azure://myaccount.blob.core.windows.net/mycontainer2/mypath2/')
  STORAGE_BLOCKED_LOCATIONS = ('azure://myaccount.blob.core.windows.net/mycontainer1/mypath1/sensitivedata/', 'azure://myaccount.blob.core.windows.net/mycontainer2/mypath2/sensitivedata/');
Copy

第 2 步:授予 Snowflake 对存储位置的访问权限

  1. 执行 DESCRIBE INTEGRATION 命令以检索许可 URL:

    DESC STORAGE INTEGRATION <integration_name>;
    
    Copy

    其中:

请注意以下列中的值:

AZURE_CONSENT_URL:

Microsoft 权限请求页面的 URL。

AZURE_MULTI_TENANT_APP_NAME:

为账户创建的 Snowflake 客户端应用程序的名称。在本部分后面的步骤中,需要授予此应用程序所需的权限,使其在受允许的存储位置上获取访问令牌。

  1. 在 Web 浏览器中,导航到 AZURE_CONSENT_URL 列中的 URL。该页面显示 Microsoft 权限请求页面。

  2. 点击 Accept 按钮。此操作允许向为 Snowflake 账户创建的 Azure 服务主体授予对租户内指定资源的访问令牌。仅当您授予服务主体对容器的适当权限时,才能成功获取访问令牌(请参阅下一步)。

    Microsoft 权限请求页面会重定向到 Snowflake 公司站点 (snowflake.com)。

  3. 登录 Microsoft Azure 门户。

  4. 导航到 Azure Services » Storage Accounts。点击要授予 Snowflake 服务主体访问权限的存储账户的名称。

  5. 点击 Access Control (IAM) » Add role assignment

  6. 选择要授予 Snowflake 服务主体的所需角色:

    • Storage Blob Data Reader 仅授予读取访问权限。此权限允许从存储账户中暂存的文件加载数据。

    • Storage Blob Data Contributor 授予读取和写入访问权限。此权限允许加载存储账户中暂存的文件内的数据,或是将数据卸载到存储账户中暂存的文件。该角色还允许执行 REMOVE 命令来移除存储账户中暂存的文件。

  7. 搜索 Snowflake 服务主体。这是 DESC STORAGE INTEGRATION 输出(第 1 步中)中 AZURE_MULTI_TENANT_APP_NAME 属性的身份。在 AZURE_MULTI_TENANT_APP_NAME 属性中搜索下划线 之前 的字符串。

    重要

    • Azure 可能需要一个小时或更长时间才能创建通过此部分中的 Microsoft 请求页面请求的 Snowflake 服务主体。如果服务主体不能立即使用,我们建议等待一两个小时,然后再次搜索。

    • 如果删除服务主体,存储集成将停止工作。

    在 Azure 存储控制台中添加角色分配
  8. 点击 Review + assign 按钮。

    备注

    • 根据 Microsoft Azure 文档,角色分配传播至多可能需要五分钟。

    • Snowflake 会将临时凭据缓存一段时间,但不能超过 60 分钟的过期时间。如果您撤消 Snowflake 的访问权限,用户或许也能够从云存储位置列出文件并加载数据,直到缓存过期。

使用 Azure 事件网格配置自动化

第 1 步:配置事件网格订阅

本部分介绍如何使用 Azure CLI 为 Azure 存储事件设置事件网格订阅。有关本部分中描述的步骤的更多信息,请参阅 Azure 文档中的以下文章:

  • https://docs.microsoft.com/en-us/azure/event-grid/custom-event-to-queue-storage (https://docs.microsoft.com/en-us/azure/event-grid/custom-event-to-queue-storage)

  • https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-event-quickstart (https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-event-quickstart)

创建资源组

事件网格 主题 提供了一个端点,来源(即 Azure 存储)会将事件发送到该端点。主题用作相关事件的集合。事件网格主题是 Azure 资源,必须放在 Azure 资源组中。

执行以下命令以创建资源组:

az group create --name <resource_group_name> --location <location>
Copy

其中:

  • resource_group_name 是新资源组的名称。

  • location 指的是 Azure 存储账户的位置,即 Snowflake 术语中的 区域

启用事件网格资源提供商

执行以下命令以注册事件网格资源提供商。请注意,仅当您以前未将事件网格与 Azure 账户搭配使用时,才需要执行此步骤:

az provider register --namespace Microsoft.EventGrid
az provider show --namespace Microsoft.EventGrid --query "registrationState"
Copy

为数据文件创建存储账户

执行以下命令以创建存储账户来存储数据文件。此账户必须是 Blob 存储(即 BlobStorage 类别)或 GPv2(即 StorageV2 类别)账户,因为只有这两种账户类型支持事件消息。

备注

如果您已经有 Blob 存储或 GPv2 账户,则可以使用该账户。

例如,创建 Blob 存储账户:

az storage account create --resource-group <resource_group_name> --name <storage_account_name> --sku Standard_LRS --location <location> --kind BlobStorage --access-tier Hot
Copy

其中:

  • resource_group_name 是在 创建资源组 中创建的资源组的名称。

  • storage_account_name 是新存储账户的名称。

  • location 是您的 Azure 存储账户的位置。

为存储队列创建存储账户

执行以下命令以创建存储账户来托管存储队列。此账户必须是 GPv2 账户,因为只有此类账户才支持将事件消息发送到存储队列。

备注

如果已经有一个 GPv2 账户,则可以使用该账户托管数据文件和存储队列。

例如,创建 GPv2 账户:

az storage account create --resource-group <resource_group_name> --name <storage_account_name> --sku Standard_LRS --location <location> --kind StorageV2
Copy

其中:

  • resource_group_name 是在 创建资源组 中创建的资源组的名称。

  • storage_account_name 是新存储账户的名称。

  • location 是您的 Azure 存储账户的位置。

创建存储队列

单个 Azure 队列存储队列可以收集许多事件网格订阅的事件消息。为获得最佳性能,Snowflake 建议创建单个存储队列以容纳与 Snowflake 相关的所有订阅。

执行以下命令以创建存储队列。存储队列会存储一组消息,在本例中是来自事件网格的事件消息:

az storage queue create --name <storage_queue_name> --account-name <storage_account_name>
Copy

其中:

导出存储账户和队列 IDs 以供参考

执行以下命令以设置存储账户和队列 IDs 的环境变量,这些指令稍后将请求这些变量:

  • Linux 或 macOS:

    export storageid=$(az storage account show --name <data_storage_account_name> --resource-group <resource_group_name> --query id --output tsv)
    export queuestorageid=$(az storage account show --name <queue_storage_account_name> --resource-group <resource_group_name> --query id --output tsv)
    export queueid="$queuestorageid/queueservices/default/queues/<storage_queue_name>"
    
    Copy
  • Windows:

    set storageid=$(az storage account show --name <data_storage_account_name> --resource-group <resource_group_name> --query id --output tsv)
    set queuestorageid=$(az storage account show --name <queue_storage_account_name> --resource-group <resource_group_name> --query id --output tsv)
    set queueid="%queuestorageid%/queueservices/default/queues/<storage_queue_name>"
    
    Copy

其中:

安装事件网格扩展程序

执行以下命令以安装 Azure CLI 的事件网格扩展程序:

az extension add --name eventgrid
Copy

创建事件网格订阅

执行以下命令以创建事件网格订阅。订阅主题可告知事件网格要跟踪哪些事件:

  • Linux 或 macOS:

    az eventgrid event-subscription create \
    --source-resource-id $storageid \
    --name <subscription_name> --endpoint-type storagequeue \
    --endpoint $queueid \
    --advanced-filter data.api stringin CopyBlob PutBlob PutBlockList FlushWithClose SftpCommit DeleteBlob DeleteFile SftpRemove
    
    Copy
  • Windows:

    az eventgrid event-subscription create \
    --source-resource-id %storageid% \
    --name <subscription_name> --endpoint-type storagequeue \
    --endpoint %queueid% \
    -advanced-filter data.api stringin CopyBlob PutBlob PutBlockList FlushWithClose SftpCommit DeleteBlob DeleteFile SftpRemove
    
    Copy

其中:

第 2 步:创建通知集成

通知集成是一个 Snowflake 对象,在 Snowflake 和第三方云消息队列服务(如 Azure 事件网格)之间提供一个接口。

备注

单个通知集成支持单个 Azure 存储队列。在多个通知集成中引用同一存储队列可能会导致目标表中缺少数据,因为事件通知会在多个通知集成之间拆分。

检索存储队列 URL 和租户 ID

  1. 登录 Microsoft Azure 门户。

  2. 导航到 Storage account » Queue service » Queues。记录在 创建存储队列 中创建的队列的 URL,以供以后参考。URL 具有以下格式:

    https://<storage_account_name>.queue.core.windows.net/<storage_queue_name>
    
    Copy
  3. 导航到 Azure Active Directory » Properties。记录 Tenant ID 值以供以后参考。需要目录 ID 或 租户 ID 来生成授予 Snowflake 访问事件网格订阅的许可 URL。

创建通知集成

使用 CREATE NOTIFICATION INTEGRATION 命令创建通知集成。

备注

  • 只有账户管理员(具有 ACCOUNTADMIN 角色的用户)或具有全局 CREATE INTEGRATION 权限的角色才能执行此 SQL 命令。

  • 通知集成的 Azure 服务主体与为存储集成创建的服务主体不同。

CREATE NOTIFICATION INTEGRATION <integration_name>
  ENABLED = true
  TYPE = QUEUE
  NOTIFICATION_PROVIDER = AZURE_STORAGE_QUEUE
  AZURE_STORAGE_QUEUE_PRIMARY_URI = '<queue_URL>'
  AZURE_TENANT_ID = '<directory_ID>';
Copy

其中:

例如:

CREATE NOTIFICATION INTEGRATION my_notification_int
  ENABLED = true
  TYPE = QUEUE
  NOTIFICATION_PROVIDER = AZURE_STORAGE_QUEUE
  AZURE_STORAGE_QUEUE_PRIMARY_URI = 'https://myqueue.queue.core.windows.net/mystoragequeue'
  AZURE_TENANT_ID = 'a123bcde-1234-5678-abc1-9abc12345678';
Copy

授予 Snowflake 对存储队列的访问权限

请注意,本部分中的特定步骤需要在本地安装 Azure CLI。

  1. 执行 DESCRIBE INTEGRATION 命令以检索许可 URL:

    DESC NOTIFICATION INTEGRATION <integration_name>;
    
    Copy

    其中:

    请注意以下列中的值:

    AZURE_CONSENT_URL:

    Microsoft 权限请求页面的 URL。

    AZURE_MULTI_TENANT_APP_NAME:

    为账户创建的 Snowflake 客户端应用程序的名称。在本部分后面的步骤中,需要授予此应用程序必要的权限,使其获取允许主题的访问令牌。

  2. 在 Web 浏览器中,导航到 AZURE_CONSENT_URL 列中的 URL。该页面显示 Microsoft 权限请求页面。

  3. 点击 Accept 按钮。此操作允许为 Snowflake 账户创建的 Azure 服务主体获取租户内任何资源的访问令牌。仅当您授予服务主体对容器的适当权限时,才能成功获取访问令牌(请参阅下一步)。

    Microsoft 权限请求页面会重定向到 Snowflake 公司站点 (snowflake.com)。

  4. 登录 Microsoft Azure 门户。

  5. 导航到 Azure Active Directory » Enterprise applications。验证是否列出了在本部分第 2 步中记录的 Snowflake 应用程序标识符。

    重要

    如果以后在 Azure AD 中删除 Snowflake 应用程序,通知集成将会停止工作。

  6. 导航到 Queues » storage_queue_name,其中 storage_queue_name 是在 创建存储队列 中创建的存储队列的名称。

  7. 点击 Access Control (IAM) » Add role assignment

  8. 搜索 Snowflake 服务主体。这是 DESC NOTIFICATION INTEGRATION 输出(第 1 步中)中 AZURE_MULTI_TENANT_APP_NAME 属性的身份。在 AZURE_MULTI_TENANT_APP_NAME 属性中搜索下划线 之前 的字符串。

    重要

    • Azure 可能需要一个小时或更长时间才能创建通过此部分中的 Microsoft 请求页面请求的 Snowflake 服务主体。如果服务主体不能立即使用,我们建议等待一两个小时,然后再次搜索。

    • 如果删除服务主体,通知集成将停止工作。

  9. 授予 Snowflake 应用程序以下权限:

    • Role: 存储队列数据消息处理者(所需的最低权限角色)或存储队列数据贡献者

    • Assign access to: Azure AD 用户、组或服务主体

    • Select: appDisplayName 值。

    Snowflake 应用程序标识符现在应列于 Storage Queue Data Message ProcessorStorage Queue Data Contributor 下方(同一对话框上)。

第 3 步:创建暂存区(如果需要)

使用 CREATE STAGE 命令创建引用 Azure 容器的外部暂存区。Snowflake 将暂存数据文件读入外部表元数据。或者,您可以使用现有的外部暂存区。

备注

  • 要配置对云存储位置的安全访问,请参阅 配置对 Cloud Storage 的安全访问 (本主题内容)。

  • 要在 CREATE STAGE 语句中引用存储集成,角色必须具有对存储集成对象的 USAGE 权限。

以下示例会在活动架构中为用户会话创建一个名为 mystage 的暂存区。云存储 URL 包括路径 files。该暂存区引用名为 my_storage_int 的存储集成。

USE SCHEMA mydb.public;

CREATE STAGE mystage
  URL='azure://myaccount.blob.core.windows.net/mycontainer/files/'
  STORAGE_INTEGRATION = my_storage_int;
Copy

备注

blob.core.windows.net 端点用于所有受支持类型的 Azure Blob 存储账户,包括 Data Lake Storage Gen2。

第 4 步:创建外部表

使用 CREATE EXTERNAL TABLE 命令创建外部表。

例如,在 mydb.public 架构中创建一个外部表,该表从 mystage 暂存区(具有 path1/ 路径)中暂存的文件读取 JSON 数据。

INTEGRATION 参数引用您在 第 2 步:创建通知集成 中创建的 my_notification_int 通知集成。集成名称必须全部大写。

请注意,提供通知集成时,默认情况下 AUTO_REFRESH 参数为 TRUE。如果没有通知集成,则 AUTO_REFRESH 始终为 FALSE

CREATE OR REPLACE EXTERNAL TABLE ext_table
 INTEGRATION = 'MY_NOTIFICATION_INT'
 WITH LOCATION = @mystage/path1/
 FILE_FORMAT = (TYPE = JSON);
Copy

具有自动刷新功能的外部暂存区现已配置完毕!

将新的或更新的数据文件添加到 Azure 容器时,事件通知会通知 Snowflake 将它们扫描到外部表元数据中。

第 5 步:手动刷新外部表元数据

使用带有 REFRESH 参数的 ALTER EXTERNAL TABLE 手动刷新一次外部表元数据,例如:

ALTER EXTERNAL TABLE ext_table REFRESH;

+---------------------------------------------+----------------+-------------------------------+
| file                                        | status         | description                   |
|---------------------------------------------+----------------+-------------------------------|
| files/path1/file1.json                      | REGISTERED_NEW | File registered successfully. |
| files/path1/file2.json                      | REGISTERED_NEW | File registered successfully. |
| files/path1/file3.json                      | REGISTERED_NEW | File registered successfully. |
+---------------------------------------------+----------------+-------------------------------+
Copy

此步骤将元数据与暂存区中的文件列表和外部表定义中的路径进行同步。此外,此步骤确保外部表可以读取指定暂存区和路径中的数据文件,并且外部表定义中没有缺失任何文件。

如果 file 列中的文件列表不符合您的期望,请验证外部表定义和外部暂存区定义中的路径。外部表定义中的任何路径都会追加到暂存区定义中指定的任何路径。有关更多信息,请参阅 CREATE EXTERNAL TABLE

重要

如果在创建外部表后,此步骤未成功完成至少一次,则在事件网格通知首次自动刷新外部表元数据之前,查询外部表将不会返回任何结果。

此步骤确保元数据与自第 4 步以来发生的文件列表的任何变更同步。此后,事件网格通知会自动触发元数据刷新。

第 6 步:配置安全性

对于将用于查询外部表的每个附加角色,请使用 GRANT <privileges> 授予对各种对象(即数据库、架构、暂存区和表)的足够的访问控制权限:

对象

权限

备注

数据库

USAGE

架构

USAGE

命名暂存区

USAGE、READ

命名文件格式

USAGE

可选;仅当 _第 3 步:创建暂存区(如果需要) 中创建的暂存区引用命名文件格式时才需要。

外部表

SELECT

语言: 中文