混合表入门¶
简介¶
混合表 是一种 Snowflake 表类型,针对混合事务和分析工作负载进行了优化。这些工作负载要求在小规模随机读取和写入时具有低延迟和高吞吐量,这些读取和写入通常是访问表中的单行。混合表强制执行唯一性和参照完整性约束,这对事务性工作负载至关重要。
您可以使用混合表以及其他 Snowflake 表和功能来支持 Unistore 工作负载,将交易和分析数据整合到一个平台中。
混合表无缝集成到现有的 Snowflake 架构中。客户连接到相同的 Snowflake 数据库服务。查询在云服务层中进行编译和优化,并在虚拟仓库的同一个查询引擎中执行。此架构有几个主要优势:
Snowflake 平台功能开箱即可支持与混合表搭配使用,例如数据治理。
您可以运行混合操作和分析查询的混合工作负载。
您可以将混合表与其他 Snowflake 表联接起来,而且查询将在同一查询引擎中以原生和高效的方式执行。不需要联合。
您可以跨混合表和其他 Snowflake 表执行原子事务。无需自行编排两阶段提交。

混合表利用行存储作为主要数据存储来提供出色的操作查询性能。当您写入混合表时,数据将直接写入行存储。数据被异步复制到对象存储中,以便在不影响持续运行工作负载的情况下为大型扫描提供更好的性能和工作负载隔离。为了提供更好的分析查询性能,一些数据也可能以列式格式缓存在您的仓库中。您只需对逻辑混合表执行 SQL 语句,查询优化器就会决定从哪里读取数据,以便提供最佳性能。您可以获得一致的数据视图,无需担心底层基础设施。
您将学习以下内容¶
在本教程中,您将学习如何:
创建并批量加载混合表。
创建并检查 UNIQUE、PRIMARY KEY 和 FOREIGN KEY 约束的执行。
运行依赖于行级锁的并发更新。
在一致的原子事务中运行多语句操作(跨混合表和标准表)。
查询混合表并将其与标准表联接。
验证安全性和治理原则是否适用于混合表和标准表。
先决条件¶
本教程假设您:
熟悉 Snowsight 界面
熟悉 SQL
使用 选择 AWS 区域 中的非试用 Snowflake 账户
能够以被授予 ACCOUNTADMIN 角色的用户身份运行
清除 混合表不支持的功能和限制
第 1 步:设置账户¶
要开始使用,请通过创建新工作表、角色、数据库对象和虚拟仓库来设置 Snowflake 账户。然后,您将能够创建两个混合表和一个标准表。请执行以下步骤:
在 Worksheets 下,点击 Snowsight 右上角的按钮 +,然后选择 SQL Worksheet。
通过选择工作表自动生成的时间戳名称并输入
Hybrid Tables - QuickStart
来重命名工作表。通过将 SQL 命令的区块复制到您的工作表中并运行它们,进而完成以下步骤。
使用 ACCOUNTADMIN 角色创建
hybrid_quickstart_role
自定义角色,然后将此角色授予当前用户。创建
hybrid_quickstart_wh
仓库和hybrid_quickstart_db
数据库。将这些对象的所有权授予新角色。使用新角色创建
data
架构。使用新仓库。(默认情况下,您创建的数据库和架构已在使用中。)
USE ROLE ACCOUNTADMIN; CREATE OR REPLACE ROLE hybrid_quickstart_role; SET my_user = CURRENT_USER(); GRANT ROLE hybrid_quickstart_role TO USER IDENTIFIER($my_user); CREATE OR REPLACE WAREHOUSE hybrid_quickstart_wh WAREHOUSE_SIZE = XSMALL, AUTO_SUSPEND = 300, AUTO_RESUME = TRUE; GRANT OWNERSHIP ON WAREHOUSE hybrid_quickstart_wh TO ROLE hybrid_quickstart_role; CREATE OR REPLACE DATABASE hybrid_quickstart_db; GRANT OWNERSHIP ON DATABASE hybrid_quickstart_db TO ROLE hybrid_quickstart_role; USE ROLE hybrid_quickstart_role; CREATE OR REPLACE SCHEMA data; USE WAREHOUSE hybrid_quickstart_wh;
第 2 步:创建并批量加载三个表¶
本教程使用 Tasty Bytes Snowflake 虚构的餐车业务来模拟向应用程序提供数据的用例。
您将创建三个表:
order_header
混合表 – 此表用于存储订单元数据,例如truck_id
、customer_id
、order_amount
等。truck
混合表 – 此表用于存储卡车元数据,例如truck_id
、franchise_id
、menu_type_id
等。truck_history
标准表 – 此表用于存储有关卡车的历史信息,使您能够跟踪随时间的变化。
您正在创建混合表和标准表,以演示它们协同工作的效果。尽管如此,混合表在定义和行为方面存在一些本质区别:
混合表需要一个或多个列上设置主键(这意味着需要创建主键索引)。
混合表允许在任何列上创建 二级索引。
PRIMARY KEY、FOREIGN KEY 和 UNIQUE 约束 都在混合表上强制执行。
混合表上的锁是 行级,而不是表级。
混合表数据位于行存储中,但也会复制到列对象存储中。
这些差异会导致:
在加载、更新或删除表数据时,支持参照完整性。
更快的 DML 操作(尤其是更新单行的操作)。
更快的查找查询。
您可以通过从暂存区或其他表(即使用 CTAS、COPY INTO <table> 或 INSERT INTO ...SELECT)将数据批量加载到混合表中。强烈建议使用 CTAS 语句将数据批量加载到混合表中,因为有几种优化方法只有在创建表时加载数据时才能应用。
创建 :doc:`文件格式 </sql-reference/sql/create-file-format>`(描述了您可以访问或加载到 Snowflake 表中的暂存数据集)以及 :doc:`暂存区 </user-guide/data-load-overview>`(Snowflake 对象,指向 Snowflake 可以访问以摄取和查询数据的云存储位置)。数据存储在可公开访问的 AWS S3 桶中,您在创建暂存区时可以引用该桶。
CREATE OR REPLACE FILE FORMAT csv_format TYPE = CSV FIELD_DELIMITER = ',' SKIP_HEADER = 1 NULL_IF = ('NULL', 'null') EMPTY_FIELD_AS_NULL = true;
CREATE OR REPLACE STAGE frostbyte_tasty_bytes_stage URL = 's3://sfquickstarts/hybrid_table_guide' FILE_FORMAT = csv_format;
现在,使用 LIST 语句返回 FROSTBYTE_TASTY_BYTES_STAGE 中的所有文件:
LIST @frostbyte_tasty_bytes_stage;
此语句应返回两条记录:一条是 TRUCK.csv
文件的记录,一个是 ORDER_HEADER.csv
文件的记录。

创建指向云存储中数据位置的暂存区后,就可以使用从 TRUCK.csv
文件中选择数据的 CTAS 命令 来创建数据并将其加载到 truck
中。请注意 truck_id
列上的 PRIMARY KEY 约束。
第二个 DDL 语句也会通过 CTAS 语句创建一个名为 truck_history
的标准表。
SET CURRENT_TIMESTAMP = CURRENT_TIMESTAMP();
CREATE OR REPLACE HYBRID TABLE truck (
truck_id NUMBER(38,0) NOT NULL,
menu_type_id NUMBER(38,0),
primary_city VARCHAR(16777216),
region VARCHAR(16777216),
iso_region VARCHAR(16777216),
country VARCHAR(16777216),
iso_country_code VARCHAR(16777216),
franchise_flag NUMBER(38,0),
year NUMBER(38,0),
make VARCHAR(16777216),
model VARCHAR(16777216),
ev_flag NUMBER(38,0),
franchise_id NUMBER(38,0),
truck_opening_date DATE,
truck_email VARCHAR NOT NULL UNIQUE,
record_start_time TIMESTAMP,
PRIMARY KEY (truck_id)
)
AS
SELECT
t.$1 AS truck_id,
t.$2 AS menu_type_id,
t.$3 AS primary_city,
t.$4 AS region,
t.$5 AS iso_region,
t.$6 AS country,
t.$7 AS iso_country_code,
t.$8 AS franchise_flag,
t.$9 AS year,
t.$10 AS make,
t.$11 AS model,
t.$12 AS ev_flag,
t.$13 AS franchise_id,
t.$14 AS truck_opening_date,
CONCAT(truck_id, '_truck@email.com') truck_email,
$CURRENT_TIMESTAMP AS record_start_time
FROM @FROSTBYTE_TASTY_BYTES_STAGE (PATTERN=>'.*TRUCK.csv') t;
CREATE OR REPLACE TABLE truck_history (
truck_id NUMBER(38,0) NOT NULL,
menu_type_id NUMBER(38,0),
primary_city VARCHAR(16777216),
region VARCHAR(16777216),
iso_region VARCHAR(16777216),
country VARCHAR(16777216),
iso_country_code VARCHAR(16777216),
franchise_flag NUMBER(38,0),
year NUMBER(38,0),
make VARCHAR(16777216),
model VARCHAR(16777216),
ev_flag NUMBER(38,0),
franchise_id NUMBER(38,0),
truck_opening_date DATE,
truck_email VARCHAR NOT NULL UNIQUE,
record_start_time TIMESTAMP,
record_end_time TIMESTAMP,
PRIMARY KEY (truck_id)
)
AS
SELECT
t.$1 AS truck_id,
t.$2 AS menu_type_id,
t.$3 AS primary_city,
t.$4 AS region,
t.$5 AS iso_region,
t.$6 AS country,
t.$7 AS iso_country_code,
t.$8 AS franchise_flag,
t.$9 AS year,
t.$10 AS make,
t.$11 AS model,
t.$12 AS ev_flag,
t.$13 AS franchise_id,
t.$14 AS truck_opening_date,
CONCAT(truck_id, '_truck@email.com') truck_email,
$CURRENT_TIMESTAMP AS record_start_time,
NULL AS record_end_time
FROM @frostbyte_tasty_bytes_stage (PATTERN=>'.*TRUCK.csv') t;
以下 DDL 语句会创建 order_header
混合表的结构。请注意 order_id
列上的 PRIMARY KEY 约束、truck
表 truck_id
列上的 FOREIGN KEY 约束,以及 order_ts
列上的二级索引。
CREATE OR REPLACE HYBRID TABLE order_header (
order_id NUMBER(38,0) NOT NULL,
truck_id NUMBER(38,0),
location_id NUMBER(19,0),
customer_id NUMBER(38,0),
discount_id FLOAT,
shift_id NUMBER(38,0),
shift_start_time TIME(9),
shift_end_time TIME(9),
order_channel VARCHAR(16777216),
order_ts TIMESTAMP_NTZ(9),
served_ts VARCHAR(16777216),
order_currency VARCHAR(3),
order_amount NUMBER(38,4),
order_tax_amount VARCHAR(16777216),
order_discount_amount VARCHAR(16777216),
order_total NUMBER(38,4),
order_status VARCHAR(16777216) DEFAULT 'INQUEUE',
PRIMARY KEY (order_id),
FOREIGN KEY (truck_id) REFERENCES TRUCK(truck_id),
INDEX IDX01_ORDER_TS(order_ts)
);
以下 DML 语句会使用以下语句将数据插入到 order_header
表中:INSERT INTO ...SELECT。
INSERT INTO order_header (
order_id,
truck_id,
location_id,
customer_id,
discount_id,
shift_id,
shift_start_time,
shift_end_time,
order_channel,
order_ts,
served_ts,
order_currency,
order_amount,
order_tax_amount,
order_discount_amount,
order_total,
order_status)
SELECT
t.$1 AS order_id,
t.$2 AS truck_id,
t.$3 AS location_id,
t.$4 AS customer_id,
t.$5 AS discount_id,
t.$6 AS shift_id,
t.$7 AS shift_start_time,
t.$8 AS shift_end_time,
t.$9 AS order_channel,
t.$10 AS order_ts,
t.$11 AS served_ts,
t.$12 AS order_currency,
t.$13 AS order_amount,
t.$14 AS order_tax_amount,
t.$15 AS order_discount_amount,
t.$16 AS order_total,
'' as order_status
FROM @frostbyte_tasty_bytes_stage (PATTERN=>'.*ORDER_HEADER.csv') t;
第 3 步:探索数据¶
之前,您创建了 hybrid_quickstart_role
角色、hybrid_quickstart_wh
仓库、hybrid_quickstart_db
数据库和 data
架构。继续使用这些对象。
您还创建并加载了 truck
、truck_history
和 order_header
表。现在,您可以运行一些查询,并熟悉这些表中的数据及其元数据。
使用 SHOW TABLES 命令可查看标准表和混合表的属性和元数据。使用 SHOW HYBRID TABLES 命令仅可查看有关混合表的信息。
SHOW TABLES LIKE '%truck%';

SHOW HYBRID TABLES LIKE '%order_header%';

使用 DESCRIBE * <object>* 命令显示表中列的信息。请注意 PRIMARY KEY 和 UNIQUE 约束。
DESCRIBE TABLE truck;

DESCRIBE TABLE order_header;

列出您具有访问权限的 混合表。
SHOW HYBRID TABLES;

列出您具有访问权限的所有 索引。请注意每个索引 is_unique
列中的值。
SHOW INDEXES;

通过运行这些简单的查询来查看表中的示例数据。
SELECT * FROM truck LIMIT 10;
SELECT * FROM truck_history LIMIT 10;
SELECT * FROM order_header LIMIT 10;
第一个查询的输出类似于以下内容:

第 4 步:测试 UNIQUE 和 FOREIGN KEY 约束的行为¶
在此步骤中,您将测试 UNIQUE 和 FOREIGN KEY 约束。在混合表上定义这些约束时,系统会强制执行这些约束。
UNIQUE 约束通过防止向列中插入重复值来保持数据完整性。FOREIGN KEY 约束与 PRIMARY KEY 约束会协同工作,以便保持引用完整性。如果所引用的表中不存在匹配的外键值,则无法将值插入到主键列中。例如,如果在引用的产品维度表中不存在产品 ID,则销售事实表中就不能记录产品 ID 100
的销售情况。
这两类约束都支持数据的准确性和一致性,适用于主要依赖可靠而快速的事务处理的应用程序。
第 4.1 步:测试 UNIQUE 约束¶
UNIQUE 约束确保列中的所有值都是不同的。在 truck
表中,您将 truck_email
列定义为 NOT NULL 和 UNIQUE。
考虑到 UNIQUE 约束,如果尝试插入具有相同电子邮件地址的两条记录,则语句将失败。要测试此行为,请运行以下命令。
首先选择现有一个电子邮件地址,然后将变量 truck_email
设置到该字符串中。然后从表中选择 truck_id
的最大值,并将另一个变量 max_truck_id
设置为该值。接下来,设置第三个变量 new_truck_id
,并将 max_truck_id
以 1 为单位递增。此过程可确保在插入新行时不会遇到“主键已存在”错误。
最后,插入新行。
SET truck_email = (SELECT truck_email FROM truck LIMIT 1);
SET max_truck_id = (SELECT MAX(truck_id) FROM truck);
SET new_truck_id = $max_truck_id+1;
INSERT INTO truck VALUES
($new_truck_id,2,'Stockholm','Stockholm län','Stockholm','Sweden','SE',1,2001,'Freightliner','MT45 Utilimaster',0,276,'2020-10-01',$truck_email,CURRENT_TIMESTAMP());
INSERT 语句失败,并且您将收到以下错误消息:
Duplicate key value violates unique constraint SYS_INDEX_TRUCK_UNIQUE_TRUCK_EMAIL
现在,创建一个新的唯一电子邮件地址,并在 truck
表中插入新记录:
SET new_unique_email = CONCAT($new_truck_id, '_truck@email.com');
INSERT INTO truck VALUES ($new_truck_id,2,'Stockholm','Stockholm län','Stockholm','Sweden','SE',1,2001,'Freightliner','MT45 Utilimaster',0,276,'2020-10-01',$new_unique_email,CURRENT_TIMESTAMP());
这一次,INSERT 语句应该会成功运行。
第 4.2 步:测试 FOREIGN KEY 约束¶
在此步骤中,您将测试 FOREIGN KEY 约束。
首先,通过执行 GET_DDL 函数显示用于创建 order_header
表的 DDL。请注意输出中 truck_id
列的 FOREIGN KEY 约束。
SELECT GET_DDL('table', 'order_header');
此命令的输出类似于以下部分结果:

现在,使用不存在的卡车 ID 尝试将新记录插入 order_header
表。
SET max_order_id = (SELECT MAX(order_id) FROM order_header);
SET new_order_id = ($max_order_id +1);
SET no_such_truck_id = -1;
INSERT INTO order_header VALUES
($new_order_id,$no_such_truck_id,6090,0,0,0,'16:00:00','23:00:00','','2022-02-18 21:38:46.000','','USD',17.0000,'','',17.0000,'');
INSERT 语句应会失败,因为它违反了 truck
表上的 FOREIGN KEY 约束。您应该会收到以下错误消息:
Foreign key constraint SYS_INDEX_ORDER_HEADER_FOREIGN_KEY_TRUCK_ID_TRUCK_TRUCK_ID was violated.
现在,使用新的 new_truck_id
变量,并将新记录插入到 order_header
表:
INSERT INTO order_header VALUES
($new_order_id,$new_truck_id,6090,0,0,0,'16:00:00','23:00:00','','2022-02-18 21:38:46.000','','USD',17.0000,'','',17.0000,'');
这一次,INSERT 语句应该会成功运行。
第 4.3 步:尝试截断 FOREIGN KEY 约束引用的表¶
接下来,您可以验证只要外键关系存在,就不能截断 FOREIGN KEY约束引用的表。运行以下 TRUNCATE TABLE 语句:
TRUNCATE TABLE truck;
语句应会失败,并且您应该会收到以下错误消息:
91458 (0A000): Hybrid table 'TRUCK' cannot be truncated as it is involved in active foreign key constraints.
第 4.4 步:删除 FOREIGN KEY 约束引用的行¶
接下来,您可以验证只要外键关系存在,就不能删除约束 FOREIGN KEY 引用的记录。运行以下 DELETE 语句:
DELETE FROM truck WHERE truck_id = $new_truck_id;
语句应会失败,并且您应该会收到以下错误消息:
Foreign keys that reference key values still exist.
要删除 FOREIGN KEY 约束引用的记录,您必须首先从 order_header
表中删除相应的记录。然后,您可以从 truck
表中删除引用的记录。运行以下 DELETE 语句:
DELETE FROM order_header WHERE order_id = $new_order_id;
DELETE FROM truck WHERE truck_id = $new_truck_id;
这两个语句都应会成功运行。
第 5 步:使用行级锁定来运行并发更新¶
与使用分区或表级锁的标准表不同,混合表会使用 行级锁 进行更新操作。行级锁允许对独立记录进行并发更新,因此事务无需等待完整的表锁。对于依赖繁重事务工作负载的应用程序,必须将锁的等待时间保持在最低水平,从而允许并发操作非常频繁地访问同一个表。
在此步骤中,您可以在 order_header
混合表中测试不同记录的并发更新。
您将使用之前创建的主要 Hybrid Tables - QuickStart
工作表,您将创建一个名为 Hybrid Tables - QuickStart Session 2
的新工作表以模拟新会话。在 Hybrid Tables - QuickStart
工作表中,您将使用 BEGIN 语句启动一个新事务,然后运行 UPDATE 语句(DML 操作)。在运行 COMMIT 事务语句之前,您将打开 Hybrid Tables - QuickStart Session 2
工作表并运行另一个 UPDATE 语句。最后,您将提交开放事务。
第 5.1 步:创建新工作表¶
在 Worksheets 下,点击 Worksheets 右上角的 + 按钮,然后选择 SQL Worksheet。
通过选择工作表自动生成的时间戳名称并输入 Hybrid Tables - QuickStart Session 2
来重命名工作表。此新工作表将仅用于当前步骤。
第 5.2 步:运行并发更新¶
首先,打开 Hybrid Tables - QuickStart
工作表。确保您使用的是正确的角色、仓库、数据库和架构,然后设置并选择 max_order_id
变量。
USE ROLE hybrid_quickstart_role;
USE WAREHOUSE hybrid_quickstart_wh;
USE DATABASE hybrid_quickstart_db;
USE SCHEMA data;
SET max_order_id = (SELECT MAX(order_id) FROM order_header);
SELECT $max_order_id;
请注意 max_order_id
变量的值。
开启新事务并运行第一个 UPDATE 语句。
BEGIN;
UPDATE order_header
SET order_status = 'COMPLETED'
WHERE order_id = $max_order_id;
请注意,您没有提交事务,因此现在符合此条件的记录上有一个开放锁:
WHERE order_id = $max_order_id
运行 SHOW TRANSACTIONS 命令,该命令应返回单个开放事务。
SHOW TRANSACTIONS;
此命令的输出类似于以下部分结果:

打开 Hybrid Tables - QuickStart Session 2
工作表。确保您使用的是正确的角色、仓库、数据库和架构,然后设置并选择 min_order_id
变量。
USE ROLE hybrid_quickstart_role;
USE WAREHOUSE hybrid_quickstart_wh;
USE DATABASE hybrid_quickstart_db;
USE SCHEMA data;
SET min_order_id = (SELECT MIN(order_id) FROM order_header);
SELECT $min_order_id;
请注意,min_order_id
值与在第一个 UPDATE 语句中使用的 max_order_id
值有所不同。运行第二个 UPDATE 语句。
UPDATE order_header
SET order_status = 'COMPLETED'
WHERE order_id = $min_order_id;
因为混合表使用行级锁,而事务会锁定行 WHERE order_id = $MAX_ORDER_ID
,UPDATE 语句成功运行。
打开 Hybrid Tables - QuickStart
工作表并提交开放事务。
COMMIT;
运行以下查询以查看更新的记录:
SELECT * FROM order_header WHERE order_status = 'COMPLETED';
此命令的输出类似于以下部分结果:

第 6 步:展示一致性¶
在此步骤中,您将了解到混合表的一项独特功能:在一个一致的原子事务中,同时访问混合表和标准表,从而轻松有效地运行多语句操作。Snowflake 交易 可保证“ACID”的原子性、一致性、隔离性和持久性属性。任何给定的事务都被视为一个原子单元;在写入时保持一致的数据库状态;与其他并发事务隔离(就像它们按顺序运行一样);并且持久提交(提交后保持提交)。
在此示例中,公司购买了一辆与现有卡车型号相同的新卡车。因此,您必须更新 truck
混合表相关记录的 year
列来反映变更。更新后,您需要及时在 truck_history
表中更新一行并插入新行。此标准表将跟踪并保留卡车车队随时间推移而发生的所有变更。所有这些步骤都是在一个明确提交的事务中完成的。
第 6.1 步:运行包含多个 DML 语句的单个事务¶
打开原始 Hybrid Tables - QuickStart
工作表。
启动新事务,以确保将后续一系列操作视为单个原子单元。然后执行多个 DML 语句:
在
truck
混合表中更新相关的卡车记录。通过设置
record_end_time
以标记其有效性的结束,进而更新truck_history
表中的相应记录。在
truck_history
表中插入新纪录,以捕获更新的信息。
最后,提交事务。
BEGIN;
SET CURRENT_TIMESTAMP = CURRENT_TIMESTAMP();
UPDATE truck SET year = '2024', record_start_time=$CURRENT_TIMESTAMP WHERE truck_id = 1;
UPDATE truck_history SET record_end_time=$CURRENT_TIMESTAMP WHERE truck_id = 1 AND record_end_time IS NULL;
INSERT INTO truck_history SELECT *, NULL AS record_end_time FROM truck WHERE truck_id = 1;
COMMIT;
第 6.2 步:检查结果¶
现在运行以下 SELECT 查询以查看 UPDATE 和 INSERT 语句的结果。
第一个查询应返回两行,第二个查询应返回一行。
SELECT * FROM truck_history WHERE truck_id = 1;
此命令的输出类似于以下部分结果:

SELECT * FROM truck WHERE truck_id = 1;
此命令的输出类似于以下部分结果:

第 7 步:将混合表联接到标准表¶
在此步骤中,您将运行用于结合混合表 (order_header
) 和标准表 (truck_history
) 的数据的 联接 查询。此查询演示了两种表类型的互操作性。
第 7.1 步:浏览表中的数据¶
之前,您创建并加载了 order_header
表。现在,您可以运行一些查询并查看一些信息,以熟悉该表。首先,使用 SHOW TABLES 命令列出数据库中的表,然后从该列表的输出中选择两列。
SHOW TABLES IN DATABASE hybrid_quickstart_db;
SELECT "name", "is_hybrid" FROM TABLE(RESULT_SCAN(last_query_id()));
此命令的输出类似于以下部分结果:

现在运行两个简单的查询:
SELECT * FROM truck_history LIMIT 10;
SELECT * FROM order_header LIMIT 10;
第二个查询的输出类似于以下部分结果:

第 7.2 步:将混合表联接到标准表¶
要将 order_header
混合表联接到 truck_history
标准表中,请运行以下 SET 语句和查询。将混合表联接到标准表不需要任何特殊语法。
SET order_id = (SELECT order_id FROM order_header LIMIT 1);
SELECT hy.*,st.*
FROM order_header AS hy JOIN truck_history AS st ON hy.truck_id = st.truck_id
WHERE hy.order_id = $order_id
AND st.record_end_time IS NULL;
联接结果类似于以下部分结果:

第 8 步:展示安全与治理¶
在此步骤中,您将运行两个与安全相关的示例,以演示 Snowflake 安全与治理 功能同样适用于标准表和混合表。
当大量数据库用户访问同一系统时,无论工作负载是事务性的、分析性的还是混合性的,角色和授予这些角色的权限都是加强安全性的标准机制。
第 8.1 步:设置混合表访问控制和用户管理¶
基于角色的访问控制 (RBAC) 对混合表和标准表的作用相同。您可以通过向某些角色授予权限来管理对 Snowflake 中混合表数据的访问。
首先,创建新 hybrid_quickstart_bi_user_role
角色。使用 ACCOUNTADMIN 角色以创建新角色。
USE ROLE ACCOUNTADMIN;
CREATE ROLE hybrid_quickstart_bi_user_role;
SET my_user = CURRENT_USER();
GRANT ROLE hybrid_quickstart_bi_user_role TO USER IDENTIFIER($my_user);
现在,您可以向新角色授予 hybrid_quickstart_wh
仓库、hybrid_quickstart_db
数据库及其所有架构的 USAGE 权限。使用 hybrid_quickstart_role
以运行 GRANT 语句。
USE ROLE hybrid_quickstart_role;
GRANT USAGE ON WAREHOUSE hybrid_quickstart_wh TO ROLE hybrid_quickstart_bi_user_role;
GRANT USAGE ON DATABASE hybrid_quickstart_db TO ROLE hybrid_quickstart_bi_user_role;
GRANT USAGE ON ALL SCHEMAS IN DATABASE hybrid_quickstart_db TO hybrid_quickstart_bi_user_role;
使用新角色 (hybrid_quickstart_bi_user_role
),并尝试从 order_header
表中选择部分数据。
USE ROLE hybrid_quickstart_bi_user_role;
USE DATABASE hybrid_quickstart_db;
USE SCHEMA data;
SELECT * FROM order_header LIMIT 10;
您无法选择任何数据,因为角色 hybrid_quickstart_bi_user_role
未被授予表中必要的 SELECT 特权。您会收到以下错误消息:
Object 'ORDER_HEADER' does not exist or not authorized.
要解决此问题,可使用角色 hybrid_quickstart_role
将 data
架构中所有表的 SELECT 权限授予 hybrid_quickstart_bi_user_role
。
USE ROLE hybrid_quickstart_role;
GRANT SELECT ON ALL TABLES IN SCHEMA DATA TO ROLE hybrid_quickstart_bi_user_role;
再次尝试从 order_header
混合表中选择数据。
USE ROLE hybrid_quickstart_bi_user_role;
SELECT * FROM order_header LIMIT 10;
这次查询成功是因为 HYBRID_QUICKSTART_BI_USER_ROLE 在层次结构的所有级别都具有相应的权限。输出类似于以下部分结果:

第 8.2 步:创建并实施掩码策略¶
在此步骤中,您将创建一个 掩码策略 并将其应用于 truck
混合表中的 truck_email
列,方法是使用 ALTER TABLE ...ALTER COLUMN 语句。掩码策略是一种标准方法,用于控制列级数据对不同角色和权限用户的可见性。
备注
要创建掩码策略,您必须使用 Enterprise Edition 账户(或更高级别的账户)。如果您使用的是 Standard Edition 账户,请跳过此步骤。有关更多信息,请参阅 Snowflake 版本。
使用 hybrid_quickstart_role
角色,然后创建新掩码策略,目的是对未授权角色的整个列值进行掩码。
USE ROLE hybrid_quickstart_role;
CREATE MASKING POLICY hide_column_values AS
(col_value VARCHAR) RETURNS VARCHAR ->
CASE WHEN CURRENT_ROLE() IN ('HYBRID_QUICKSTART_ROLE') THEN col_value
ELSE '***MASKED***'
END;
现在,将此策略应用到混合表。
ALTER TABLE truck MODIFY COLUMN truck_email
SET MASKING POLICY hide_column_values USING (truck_email);
因为您目前使用的是 hybrid_quickstart_role
,所以 truck_email
列 不 应进行掩码。运行以下查询:
SELECT * FROM truck LIMIT 10;

切换到 HYBRID_QUICKSTART_BI_USER_ROLE
并再次运行查询。现在,TRUCK_EMAIL
列应进行掩码。
USE ROLE hybrid_quickstart_bi_user_role;
SELECT * FROM truck LIMIT 10;

第 9 步:清理、结论和延伸阅读¶
清理¶
要清理 Snowflake 环境,请运行以下 SQL 语句:
USE ROLE hybrid_quickstart_role;
USE WAREHOUSE hybrid_quickstart_wh;
USE DATABASE hybrid_quickstart_db;
USE SCHEMA data;
DROP DATABASE hybrid_quickstart_db;
DROP WAREHOUSE hybrid_quickstart_wh;
USE ROLE ACCOUNTADMIN;
DROP ROLE hybrid_quickstart_role;
DROP ROLE hybrid_quickstart_bi_user_role;
最后,手动删除 Hybrid Tables - QuickStart
和 Hybrid Tables - QuickStart Session 2
工作表。
您学到的内容¶
在本教程中,您学习了如何:
创建并批量加载混合表。
创建并检查 UNIQUE、PRIMARY KEY 和 FOREIGN KEY 约束的执行。
运行依赖于行级锁的并发更新。
在一致的原子事务中运行多语句操作(跨混合表和标准表)。
查询混合表并将其与标准表联接。
验证安全性和治理原则是否适用于混合表和标准表。