教程:代码中的 Snowflake Data Clean Room 入门¶
简介¶
本教程面向将在代码中创建或使用 Snowflake Data Clean Room 的开发者。本教程使用 SQL 代码,但您可以调整此处显示的信息,以 Snowflake 支持的任何编码语言创建和使用 Clean Room。
您将学习以下内容¶
本教程将向您展示如何使用 Snowflake Data Clean Room API 在 Clean Room 中创建和共享基本模板。它还将向您展示如何在与您共享的 Clean Room 内使用 API 运行分析。
本教程将创建一个 Clean Room,其中包含一个由提供商提供的表、一个由使用者提供的表,以及一个由提供商定义的模板,该模板在两个表上定义了一个非常简单的 JOIN 查询。使用者运行模板。
要求¶
您应该对 Snowflake 有基本的了解,在开始本教程之前,您还应该阅读 关于 Snowflake Data Clean Room。
您必须拥有两个 Snowflake 账户的访问权限。一个用作提供商账户(用于创建 Clean Room 的账户),另一个用作使用者账户(共享对象和查询运行者)。
两个账户都必须安装 Snowflake Data Clean Room 环境。如果您没有在每个账户中安装环境,您可以 自己安装,或者请 Snowflake 管理员为您安装。
两个账户都必须是 容量账户,而不是按需账户。
两个账户应该位于 Snowflake 的同一组织中。
提供商账户必须是 Enterprise Edition 或更高版本。使用者账户可以是 Standard Edition 或更高版本。
使用者账户必须添加到提供商账户中 Web 应用程序的 Collaborators 页面。
两个账户都必须被授予 SAMOOHA_APP_ROLE。
对于本教程,两个账户必须在同一个云区域中。您可以通过运行 SELECT CURRENT_REGION() 来确定您的云区域;
对于本教程,两个账户都必须在同一个组织中。
配置您的环境¶
要求您的 Clean Room 管理员将您作为用户添加到两个不同的账户。选择一个作为提供商,一个作为使用者。
在两个独立的浏览器选项卡(每个账户一个)中 登录 Snowsight。决定哪个账户用作提供商,哪个账户用作使用者。
在每个账户中打开一个新的笔记本。将提供商笔记本命名为“Test provider”,将使用者笔记本命名为“Test consumer”。
本教程的其余部分将说明是否在提供商账户或使用者账户中执行所需的操作。
提供商:概述¶
下面是 Clean Room 的创建步骤摘要:
创建要在 Clean Room 中共享的测试数据。
创建您的 Clean Room。
将您创建的数据引入 Clean Room。
对数据设置联接权限,以指定使用者查询时可以联接哪些列。
为您的 Clean Room 创建模板。一个 Clean Room 模板使用 JinjaSQL 编写,它在运行时评估为 SQL 查询。大多数模板都包含变量,允许协作者在运行时指定表和列名称、WHERE 子句条件等。Clean Room 协作者在 Clean Room 中选择并运行模板。
指定 Clean Room 的默认版本。
添加可以访问您的 Clean Room 的使用者。在本教程中,使用者必须是 Snowflake 用户,具有由 Clean Room 管理员批准的账户。
发布 Clean Room,使其可供受邀使用者使用。
备注
术语 协作者 在上面用于模板,因为根据 Clean Room 的配置方式,提供商和使用者都可以创建或运行模板。本教程仅展示如何启用使用者运行模板。
提供商:创建测试数据¶
在您的提供商账户笔记本中开始工作。
首先,您将根据 SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS 表中 1,000 行样本测试数据创建一个表。您将使用该表作为 Clean Room 中的提供商数据。
使用允许您创建数据库的角色。此处的示例使用 ACCOUNTADMIN,但您可以使用任何支持创建表的角色。
USE WAREHOUSE app_wh;
USE ROLE ACCOUNTADMIN;
-- Using ACCOUNTADMIN role because you need a role that allows you to create a database.
-- Feel free to use any other role that can create a database.
-- Generate a provider dataset based on the first 1,000 rows of sample data.
CREATE DATABASE IF NOT EXISTS cleanroom_tut_db;
CREATE SCHEMA IF NOT EXISTS cleanroom_tut_db.cleanroom_tut_sch;
CREATE TABLE IF NOT EXISTS cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table AS
SELECT TOP 1000 * FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS ORDER BY HASHED_EMAIL ASC;
DESCRIBE TABLE cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table;
提供商:创建 Clean Room¶
Clean Room 开始时没有数据,没有用户,只有默认属性。
下面的代码段将创建一个只能在组织内部访问的 Clean Room(因此标记为 INTERNAL)。要在组织外部共享 Clean Room,需要本教程不涉及的额外步骤。
您必须使用 SAMOOHA_APP_ROLE 进行几乎所有的 Clean Room 操作。
USE ROLE samooha_app_role;
SET cleanroom_name = 'Developer Tutorial';
CALL samooha_by_snowflake_local_db.provider.cleanroom_init($cleanroom_name, 'INTERNAL');
提供商:将数据引入 Clean Room¶
我们将您的测试数据引入 Clean Room。
将数据引入 Clean Room 需要以下两个步骤:
注册数据
将数据导入 Clean Room
注册数据¶
导入数据的第一步是 注册 数据库、架构或对象。这将向 Clean Room 原生应用程序授予 SELECT 权限,以便它可以读取您的数据。此步骤必须由能向其他角色授予 SELECT 权限的角色完成。您可以注册整个数据库,也可以注册数据库内的特定架构、表或视图,具体取决于您想要的控制级别。
本示例使用 ACCOUNTADMIN 角色,但在您自己的环境中,请使用任何可以授予该能力的角色。
请注意,您还可以 使用 Web 应用程序注册数据。
在现实世界中,Clean Room 管理员通常为所有 Clean Room 创建者预先注册数据,您可以跳过此步骤。
USE ROLE ACCOUNTADMIN;
CALL samooha_by_snowflake_local_db.provider.register_db('cleanroom_tut_db');
将数据导入 Clean Room¶
将数据导入名为 链接 的 Clean Room。提供商和使用者都可以将其数据链接到 Clean Room(并设置关于如何使用数据的规则,这将在后面介绍)。链接到 Clean Room 的视图或表的通用术语是 数据集。
当您链接数据时,Clean Room 会创建一个链接到您的源数据的只读视图。此 Clean Room 视图是 Clean Room 内的安全加密视图,只有 Clean Room 内的模板才能访问。该视图从源数据中剥离了 Snowflake 策略,如聚合策略和联接策略;Clean Room 支持自己的保护和隐私设置。您的模板会访问此安全视图,而不是源数据,尽管源名称在 SQL 查询中使用。
与注册不同,链接发生在单个表或视图级别,您可以在一次调用中链接多个项目。
将前面创建的表链接到 Clean Room:
-- Back to samooha_app_role until you need to clean things up at the end.
USE ROLE samooha_app_role;
CALL samooha_by_snowflake_local_db.provider.link_datasets($cleanroom_name,
['cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table']);
CALL samooha_by_snowflake_local_db.provider.view_provider_datasets($cleanroom_name);
提供商:为数据设置联接策略¶
提供商和使用者都可以为自己的数据指定 联接策略。Clean Room 联接策略指定表中哪些列可由该 Clean Room 中的查询联接。这样可以更好地控制其他人如何在 Clean Room 中使用您的数据。
请注意,Clean Room 联接策略与 Snowflake 联接策略 不同。Snowflake 联接策略和所有其他表策略在链接到 Clean Room 时会从表中剥离。
提供 Clean Room 的可联接列的列表。在 Clean Room 中使用 INNER JOIN 或 OUTER JOIN 语句时,无法联接此处未列出的任何列。使用每个列的格式 database_name.schema_name.table_or_view_name:column_name
为表指定可联接列。
-- Limit joinable columns in this table to age_band, region_code, and device_type
CALL samooha_by_snowflake_local_db.provider.set_join_policy($cleanroom_name,
['cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:age_band',
'cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:region_code',
'cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:device_type']);
CALL samooha_by_snowflake_local_db.provider.view_join_policy($cleanroom_name);
提供商:添加您的模板¶
Clean Room 模板是评估为 SELECT 查询的 JinjaSQL 模板。此查询有权访问链接到 Clean Room 的所有数据集,但需遵守联接策略和列策略。
本教程不会介绍关于设计 JinjaSQL 模板的详细信息,但下面是您尝试实现的 SQL 查询:
SELECT COUNT(*), group_by_col FROM Consumer_Table AS C
INNER JOIN Provider_Table AS P
ON C.join_col = P.join_col
GROUP BY group_col;
查询只需在指定的联接列上联接一个提供商和一个使用者表,按指定的分组列分组,并推算每个组的组值和计数。这是当用户运行模板时将在 Clean Room 中运行的查询。
下面是用于相同查询的 JinjaSQL 模板,在使用者可以指定表或列的地方添加变量。在使用者指定变量后,它将评估为类似于上面查询的 SQL 查询,但采用使用者提供的表和列名称。
SELECT COUNT(*), IDENTIFIER({{group_by_col | column_policy}}) FROM IDENTIFIER({{my_table[0]}}) AS C
INNER JOIN IDENTIFIER({{source_table[0]}}) AS P
ON IDENTIFIER({{consumer_join_col | join_policy}}) = IDENTIFIER({{provider_join_col | join_policy}})
GROUP BY IDENTIFIER({{group_by_col | column_policy}});
关于模板的一些备注:
被 {{大括号}} 包围的内容是使用者在运行模板时传入的命名变量。以下变量由使用者传入:
group_by_col
、consumer_join_col
、provider_join_col
my_table
和source_table
数组是由系统创建的全局变量,由调用者传入的使用者和提供商表名填充。这些表必须由使用者和提供商链接到 Clean Room。所有提供商表在查询中必须采用别名
p
。所有使用者表必须采用别名c
。如果您使用多个表,请使用以 1 开头的后缀作为它们的别名,因此:提供商表的别名为p
、p1
、p2
、p3
等,使用者表别名为c
、c1
、c2
、c3
等。(p
和p0
是等效的。)Snowflake Data Clean Room 支持一些自定义 JinjaSQL 筛选器,对变量进行操作。
column_policy
和row_policy
筛选器验证它们应用到的列是否符合该 Clean Room 中的列和行策略,否则模板运行请求将失败。因此,{{ consumer_join_col | join_policy }}
会验证传递给consumer_join_col
的值是否符合提供商和使用者在此 Clean Room 中设置的联接策略。用作标识符的变量必须先由 IDENTIFIER 函数处理,然后才能在 SQL 中使用。
将模板添加到 Clean Room:
-- Add the template
SET template_name = 'overlap_template';
CALL samooha_by_snowflake_local_db.provider.add_custom_sql_template(
$cleanroom_name,
$template_name,
$$
SELECT COUNT(*), IDENTIFIER({{group_by_col | column_policy}}) FROM IDENTIFIER({{my_table[0]}}) AS C
INNER JOIN IDENTIFIER({{source_table[0]}}) AS P
ON IDENTIFIER({{consumer_join_col | join_policy}}) = IDENTIFIER({{provider_join_col | join_policy}})
GROUP BY IDENTIFIER({{group_by_col | column_policy}});
$$);
CALL samooha_by_snowflake_local_db.provider.view_added_templates($cleanroom_name);
提供商:设置列策略¶
Clean Room 中的每一方都可以设置 column_policy,以限制其他方可以在结果中显示的列。Clean Room 中的列策略会列出所有可以投射的列;不能投射其他列。提供商为其表设置列策略;使用者为其表设置列策略。
列策略与 Clean Room 中的特定表和模板绑定。您可以允许在不同的模板中显示不同的列。相同列不能同时采用联接策略和列策略。
请注意,仅当模板使用模板中的 column_policy
和 row_policy
筛选器时,才会强制实施列策略和联接策略。另外,如果您不指定列策略,则意味着可以投射所有列;同样,不指定联接策略,则意味着可以联接所有列。
下面说明了如何允许在我们刚刚创建的模板中投射三列数据。列语法为 template_name:table_name:column_name
-- Set column policies. Column policies are tied to a specific template and table, so we
-- needed to add the template first.
CALL samooha_by_snowflake_local_db.provider.set_column_policy($cleanroom_name,
[$template_name || ':cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:STATUS',
$template_name || ':cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:AGE_BAND',
$template_name || ':cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table:DAYS_ACTIVE']);
CALL samooha_by_snowflake_local_db.provider.view_column_policy($cleanroom_name);
提供商:添加版本指令¶
每个 Clean Room 都有一个版本号,由主要值、次要值和补丁值组成。您需要指定向使用者提供哪个版本的 Clean Room:这称为 默认版本指令。
这是第一个版本,所以版本号是 1.0.0。
CALL samooha_by_snowflake_local_db.provider.set_default_release_directive($cleanroom_name, 'V1_0', '0');
每次您将代码上传到 Clean Room 时,Snowflake 都会创建一个新版本的 Clean Room。如果您希望用户获得最新版本,您需要对新版本再次调用此过程。您不会上传代码,因此您无需再次调用此代码。
提供商:添加使用者¶
现在,指定哪些账户可以作为使用者使用您的 Clean Room。共享 Clean Room 时的几个要求:
用户必须采用已安装 Clean Room 环境的 Snowflake 账户。可以与非 Snowflake 账户共用一个 Clean Room,但此处没有涉及。
使用者账户必须与提供商账户位于同一云区域。您可以跨区域共享,但这需要额外的配置(此处没有涉及)。
使用者账户必须添加到提供商账户中的 Collaborators 页面。只有添加到某个账户的协作者列表的账户才能受邀联接在该账户中创建的 Clean Room。
账户定位器可通过在使用者账户中运行以下过程获得:
SELECT CURRENT_ACCOUNT();
账户名称的格式为
org_name.account_name
。您可以通过在使用者账户中运行以下过程来获取这些值:SELECT CURRENT_ORGANIZATION_NAME();
SELECT CURRENT_ACCOUNT_NAME();
CALL samooha_by_snowflake_local_db.provider.add_consumers(
$cleanroom_name,
<CONSUMER_LOCATOR>,
<ORG_NAME>.<ACCOUNT_NAME>);
CALL samooha_by_snowflake_local_db.provider.view_consumers($cleanroom_name);
提供商:发布 Clean Room¶
最后,您可以发布 Clean Room。这样一来,Clean Room 就可供您在上面添加的使用者使用。该过程需要一分钟或更长时间才能完成。
-- Publish the clean room.
CALL samooha_by_snowflake_local_db.provider.create_or_update_cleanroom_listing($cleanroom_name);
该过程完成后,在提供商账户 Clean Room Web 应用程序的 Created 选项卡中,以及在使用者账户 Web 应用程序的 Invited 选项卡中,您应该会看到 Clean Room 已列出,带标签“Powered by Dev Edition”。使用者账户将收到一封邀请电子邮件,Clean Room 应该会显示在使用者账户 Web 应用程序的 Invited 选项卡中。
恭喜:您发布了第一个 Clean Room!
现在转到使用者账户以使用 Clean Room。
使用者:安装(联接)Clean Room¶
切换到 Snowsight 中的使用者账户。您可以在浏览器中打开第二个选项卡,或使用 账户切换器。
使用使用者账户登录后,在使用者笔记本中设置您的环境:
USE WAREHOUSE app_wh;
USE ROLE samooha_app_role;
安装您刚刚发布和共享的 Clean Room。
备注
如果您打开此账户的 Web 应用程序,您将在 Invited 选项卡中看到此 Clean Room,带标签 Powered by Dev Edition,表示它是使用代码创建。您可以从那里安装 Clean Room,但我们会在此处向您展示如何使用代码创建。
要安装 Clean Room,您必须同时指定 Clean Room 名称和与您共享 Clean Room 的提供商的账户定位器。指定 Clean Room 名称和账户定位器,有助于消除多个 Clean Room 邀请的歧义。您可以在提供商账户中运行 SELECT CURRENT_ACCOUNT();
,以获取提供商定位器。
安装可能需要几分钟。
SET cleanroom_name = 'Developer Tutorial';
CALL samooha_by_snowflake_local_db.consumer.install_cleanroom($cleanroom_name, <PROVIDER_LOCATOR>);
使用者:创建和链接您的数据¶
现在,在此 Clean Room 中创建并添加数据集,类似于提供商的数据集,但使用示例数据底部的 1,000 行。
USE ROLE ACCOUNTADMIN;
CREATE DATABASE IF NOT EXISTS cleanroom_tut_db;
CREATE SCHEMA IF NOT EXISTS cleanroom_tut_db.cleanroom_tut_sch;
CREATE TABLE IF NOT EXISTS cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table AS
SELECT TOP 1000 * FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS ORDER BY HASHED_EMAIL DESC;
DESCRIBE TABLE cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table;
创建源数据后,您必须注册并将其链接到 Clean Room,就像您作为提供商所做的那样。
-- You need to use a role that has ownership of the object to be registered, probably not samooha_app_role.
USE ROLE ACCOUNTADMIN;
CALL samooha_by_snowflake_local_db.library.register_objects(['cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table']);
-- Drop back down to samooha_app_role for the other actions.
USE ROLE samooha_app_role;
CALL samooha_by_snowflake_local_db.consumer.link_datasets($cleanroom_name, ['cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table']);
CALL samooha_by_snowflake_local_db.consumer.view_consumer_datasets($cleanroom_name);
使用者:为数据设置联接策略¶
现在,您可以为数据设置联接策略,就像您在提供商账户中所做的那样。设置使用者联接策略在本示例中多余,因为只有使用者才能在此 Clean Room 中运行模板。而且,由于您自己运行模板,您知道哪些列应该可以联接。但是,在实际使用中,为您的数据设置联接策略很有意义,可以防止 Clean Room 支持允许提供商运行模板。
-- Allow same three columns in your data to be joined.
CALL samooha_by_snowflake_local_db.consumer.set_join_policy($cleanroom_name,
['cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table:age_band',
'cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table:region_code',
'cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table:device_type']);
使用者:准备您的查询¶
要运行查询,您需要以下信息:
要运行的模板的名称。
要提供给模板的表的名称。
要提供给模板的提供商表的名称。
要传入的任何其他名称/值变量。在我们的模板中,我们需要传入提供商表和使用者表中的联接列名称。
检查模板¶
您可以检查模板,查看确切的语法,并查看您需要传入的内容。
-- List templates in the clean room, then examine the template details
CALL samooha_by_snowflake_local_db.consumer.view_added_templates($cleanroom_name);
SET template_name = 'overlap_template';
CALL samooha_by_snowflake_local_db.consumer.view_template_definition($cleanroom_name, $template_name);
您可以看到,您需要传入提供商表和列名称、使用者表和列名称以及分组列。
列出可用的提供商表¶
查看提供商向 Clean Room 添加了哪些表。
-- Table name to use is in the LINKED_TABLE column in the results.
CALL samooha_by_snowflake_local_db.consumer.view_provider_datasets($cleanroom_name);
检查可联接的和可投射的列¶
查看可以从提供商的数据联接或投射哪些列。
-- See which provider columns can be joined on
CALL samooha_by_snowflake_local_db.consumer.view_provider_join_policy($cleanroom_name);
-- See which provider columns can be projected
CALL samooha_by_snowflake_local_db.consumer.view_provider_column_policy($cleanroom_name);
运行分析¶
现在我们知道查询需要什么、哪些提供商数据可用以及可以使用数据执行的操作,您可以选择要传入的值。
如果模板中的列名不明确,您必须完全限定具有表名的列。您必须使用表别名(而不是实际的表名)作为表名。请记住,此模板中提供商表的别名是 p
,使用者表的别名是 c
。由于内部原因,您必须使用小写 p
和 c
作为别名。
提供商表:唯一的选择是
cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table
。使用者表:唯一的选择是
cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table
。consumer_join_col
:我们选择age_band
。使用者表中完全限定的列名为c.age_band
。provider_join_col
:我们需要联接类似的列,所以完全限定名称为p.age_band
。group_by_col
:从剩余的可投射列中选取提供商列或使用者列。我们将使用p.device_type
,但您可以选择consumer.view_provider_column_policy
返回的任何其他提供商或使用者列。
这些值传入 consumer.run_analysis
,如下所示:
CALL samooha_by_snowflake_local_db.consumer.run_analysis(
$cleanroom_name,
$template_name,
['cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table'],
['cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table'],
OBJECT_CONSTRUCT(
'consumer_join_col','c.age_band',
'provider_join_col','p.age_band',
'group_by_col','p.status'
),
FALSE
);
小技巧
最后一个参数表示不应缓存结果。我们建议不要在测试期间缓存结果,这会强制 API 重新运行查询,即使您传入相同的查询也是如此。在不更改查询的情况下更改基础模板时,这很有用。
恭喜!您应该会在 Snowsight 中看到模板结果。
此处未涉及的其他功能允许您将这些结果直接导出到自己的 Snowflake 账户,或导出到名为 Activation 的流程中经批准的第三方服务。
在 Snowflake Clean Rooms 开发者指南 中,查看更多使用案例并了解更多 Clean Room 功能。
两个账户:清理¶
现在,我们来清理您创建的所有资源。
请注意,您需要使用在创建源表时所用的相同角色来删除源表。
提供商清理¶
在您的提供商账中运行此代码:
USE ROLE samooha_app_role;
CALL samooha_by_snowflake_local_db.provider.drop_cleanroom($cleanroom_name);
USE role ACCOUNTADMIN;
DROP TABLE cleanroom_tut_db.cleanroom_tut_sch.demo_provider_table;
DROP DATABASE cleanroom_tut_db;
使用者清理¶
在您的使用者账户中运行此代码:
USE ROLE samooha_app_role;
CALL samooha_by_snowflake_local_db.consumer.uninstall_cleanroom($cleanroom_name);
USE ROLE ACCOUNTADMIN;
DROP VIEW cleanroom_tut_db.cleanroom_tut_sch.demo_consumer_table;
DROP DATABASE cleanroom_tut_db;