混合表入门

简介

混合表 是一种 Snowflake 表类型,针对混合事务和分析工作负载进行了优化。这些工作负载要求在小规模随机读取和写入时具有低延迟和高吞吐量,这些读取和写入通常是访问表中的单行。混合表强制执行唯一性和参照完整性约束,这对事务性工作负载至关重要。

您可以使用混合表以及其他 Snowflake 表和功能来支持 Unistore 工作负载,将交易和分析数据整合到一个平台中。

混合表无缝集成到现有的 Snowflake 架构中。客户连接到相同的 Snowflake 数据库服务。查询在云服务层中进行编译和优化,并在虚拟仓库的同一个查询引擎中执行。此架构有几个主要优势:

  • Snowflake 平台功能开箱即可支持与混合表搭配使用,例如数据治理。

  • 您可以运行混合操作和分析查询的混合工作负载。

  • 您可以将混合表与其他 Snowflake 表联接起来,而且查询将在同一查询引擎中以原生和高效的方式执行。不需要联合。

  • 您可以跨混合表和其他 Snowflake 表执行原子事务。无需自行编排两阶段提交。

Unistore 架构

混合表利用行存储作为主要数据存储来提供出色的操作查询性能。当您写入混合表时,数据将直接写入行存储。数据被异步复制到对象存储中,以便在不影响持续运行工作负载的情况下为大型扫描提供更好的性能和工作负载隔离。为了提供更好的分析查询性能,一些数据也可能以列式格式缓存在您的仓库中。您只需对逻辑混合表执行 SQL 语句,查询优化器就会决定从哪里读取数据,以便提供最佳性能。您可以获得一致的数据视图,无需担心底层基础设施。

您将学习以下内容

在本教程中,您将学习如何:

  • 创建并批量加载混合表。

  • 创建并检查 UNIQUE、PRIMARY KEY 和 FOREIGN KEY 约束的执行。

  • 运行依赖于行级锁的并发更新。

  • 在一致的原子事务中运行多语句操作(跨混合表和标准表)。

  • 查询混合表并将其与标准表联接。

  • 验证安全性和治理原则是否适用于混合表和标准表。

先决条件

本教程假设您:

第 1 步:设置账户

要开始使用,请通过创建新工作表、角色、数据库对象和虚拟仓库来设置 Snowflake 账户。然后,您将能够创建两个混合表和一个标准表。请执行以下步骤:

  1. Worksheets 下,点击 Snowsight 右上角的按钮 +,然后选择 SQL Worksheet

  2. 通过选择工作表自动生成的时间戳名称并输入 Hybrid Tables - QuickStart 来重命名工作表。

  3. 通过将 SQL 命令的区块复制到您的工作表中并运行它们,进而完成以下步骤。

    1. 使用 ACCOUNTADMIN 角色创建 hybrid_quickstart_role 自定义角色,然后将此角色授予当前用户。

    2. 创建 hybrid_quickstart_wh 仓库和 hybrid_quickstart_db 数据库。将这些对象的所有权授予新角色。

    3. 使用新角色创建 data 架构。

    4. 使用新仓库。(默认情况下,您创建的数据库和架构已在使用中。)

    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;
    
    Copy

第 2 步:创建并批量加载三个表

本教程使用 Tasty Bytes Snowflake 虚构的餐车业务来模拟向应用程序提供数据的用例。

您将创建三个表:

  • order_header 混合表 – 此表用于存储订单元数据,例如 truck_idcustomer_idorder_amount 等。

  • truck 混合表 – 此表用于存储卡车元数据,例如 truck_idfranchise_idmenu_type_id 等。

  • truck_history 标准表 – 此表用于存储有关卡车的历史信息,使您能够跟踪随时间的变化。

您正在创建混合表和标准表,以演示它们协同工作的效果。尽管如此,混合表在定义和行为方面存在一些本质区别:

  • 混合表需要一个或多个列上设置主键(这意味着需要创建主键索引)。

  • 混合表允许在任何列上创建 二级索引

  • PRIMARY KEY、FOREIGN KEY 和 UNIQUE 约束 都在混合表上强制执行。

  • 混合表上的锁是 行级,而不是表级。

  • 混合表数据位于行存储中,但也会复制到列对象存储中。

这些差异会导致:

  • 在加载、更新或删除表数据时,支持参照完整性。

  • 更快的 DML 操作(尤其是更新单行的操作)。

  • 更快的查找查询。

您可以通过从暂存区或其他表(即使用 CTASCOPY 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;
Copy

现在,使用 LIST 语句返回 FROSTBYTE_TASTY_BYTES_STAGE 中的所有文件:

LIST @frostbyte_tasty_bytes_stage;
Copy

此语句应返回两条记录:一条是 TRUCK.csv 文件的记录,一个是 ORDER_HEADER.csv 文件的记录。

LIST 命令的输出,其中包含两个文件的名称和大小。

创建指向云存储中数据位置的暂存区后,就可以使用从 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;
Copy

以下 DDL 语句会创建 order_header 混合表的结构。请注意 order_id 列上的 PRIMARY KEY 约束、trucktruck_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)
);
Copy

以下 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;
Copy

第 3 步:探索数据

之前,您创建了 hybrid_quickstart_role 角色、hybrid_quickstart_wh 仓库、hybrid_quickstart_db 数据库和 data 架构。继续使用这些对象。

您还创建并加载了 trucktruck_historyorder_header 表。现在,您可以运行一些查询,并熟悉这些表中的数据及其元数据。

使用 SHOW TABLES 命令可查看标准表和混合表的属性和元数据。使用 SHOW HYBRID TABLES 命令仅可查看有关混合表的信息。

SHOW TABLES LIKE '%truck%';
Copy
卡车表 SHOW TABLES 命令的输出
SHOW HYBRID TABLES LIKE '%order_header%';
Copy
order_header 表 SHOW HYBRID TABLES 命令的输出

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

DESCRIBE TABLE truck;
Copy
卡车表 DESCRIBE 命令的输出
DESCRIBE TABLE order_header;
Copy
order_header 表 DESCRIBE 命令的输出

列出您具有访问权限的 混合表

SHOW HYBRID TABLES;
Copy
SHOW HYBRID TABLES 命令的输出

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

SHOW INDEXES;
Copy
SHOW INDEXES 命令的输出

通过运行这些简单的查询来查看表中的示例数据。

SELECT * FROM truck LIMIT 10;
SELECT * FROM truck_history LIMIT 10;
SELECT * FROM order_header LIMIT 10;
Copy

第一个查询的输出类似于以下内容:

针对卡车表 SELECT 查询的输出

第 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());
Copy

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());
Copy

这一次,INSERT 语句应该会成功运行。

第 4.2 步:测试 FOREIGN KEY 约束

在此步骤中,您将测试 FOREIGN KEY 约束。

首先,通过执行 GET_DDL 函数显示用于创建 order_header 表的 DDL。请注意输出中 truck_id 列的 FOREIGN KEY 约束。

SELECT GET_DDL('table', 'order_header');
Copy

此命令的输出类似于以下部分结果:

order_header 表上 get_ddl 的输出

现在,使用不存在的卡车 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,'');
Copy

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,'');
Copy

这一次,INSERT 语句应该会成功运行。

第 4.3 步:尝试截断 FOREIGN KEY 约束引用的表

接下来,您可以验证只要外键关系存在,就不能截断 FOREIGN KEY约束引用的表。运行以下 TRUNCATE TABLE 语句:

TRUNCATE TABLE truck;
Copy

语句应会失败,并且您应该会收到以下错误消息:

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;
Copy

语句应会失败,并且您应该会收到以下错误消息:

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;
Copy

这两个语句都应会成功运行。

第 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;
Copy

请注意 max_order_id 变量的值。

开启新事务并运行第一个 UPDATE 语句。

BEGIN;
UPDATE order_header
  SET order_status = 'COMPLETED'
  WHERE order_id = $max_order_id;
Copy

请注意,您没有提交事务,因此现在符合此条件的记录上有一个开放锁:

WHERE order_id = $max_order_id
Copy

运行 SHOW TRANSACTIONS 命令,该命令应返回单个开放事务。

SHOW TRANSACTIONS;
Copy

此命令的输出类似于以下部分结果:

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;
Copy
SET min_order_id = (SELECT MIN(order_id) FROM order_header);
SELECT $min_order_id;
Copy

请注意,min_order_id 值与在第一个 UPDATE 语句中使用的 max_order_id 值有所不同。运行第二个 UPDATE 语句。

UPDATE order_header
  SET order_status = 'COMPLETED'
  WHERE order_id = $min_order_id;
Copy

因为混合表使用行级锁,而事务会锁定行 WHERE order_id = $MAX_ORDER_ID,UPDATE 语句成功运行。

打开 Hybrid Tables - QuickStart 工作表并提交开放事务。

COMMIT;
Copy

运行以下查询以查看更新的记录:

SELECT * FROM order_header WHERE order_status = 'COMPLETED';
Copy

此命令的输出类似于以下部分结果:

order_status 已完成的 order_header 表中的 SELECT 结果

第 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;
Copy

第 6.2 步:检查结果

现在运行以下 SELECT 查询以查看 UPDATE 和 INSERT 语句的结果。

第一个查询应返回两行,第二个查询应返回一行。

SELECT * FROM truck_history WHERE truck_id = 1;
Copy

此命令的输出类似于以下部分结果:

返回两行的 truck_history 查询的输出
SELECT * FROM truck WHERE truck_id = 1;
Copy

此命令的输出类似于以下部分结果:

返回一行的卡车查询的输出

第 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()));
Copy

此命令的输出类似于以下部分结果:

显示表是否为混合表的查询

现在运行两个简单的查询:

SELECT * FROM truck_history LIMIT 10;
SELECT * FROM order_header LIMIT 10;
Copy

第二个查询的输出类似于以下部分结果:

从 order_header 表中返回 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;
Copy

联接结果类似于以下部分结果:

返回混合表和标准表之间的联接结果的查询

第 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);
Copy

现在,您可以向新角色授予 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;
Copy

使用新角色 (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;
Copy

您无法选择任何数据,因为角色 hybrid_quickstart_bi_user_role 未被授予表中必要的 SELECT 特权。您会收到以下错误消息:

Object 'ORDER_HEADER' does not exist or not authorized.

要解决此问题,可使用角色 hybrid_quickstart_roledata 架构中所有表的 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;
Copy

再次尝试从 order_header 混合表中选择数据。

USE ROLE hybrid_quickstart_bi_user_role;
SELECT * FROM order_header LIMIT 10;
Copy

这次查询成功是因为 HYBRID_QUICKSTART_BI_USER_ROLE 在层次结构的所有级别都具有相应的权限。输出类似于以下部分结果:

现在允许在 DATA 架构授权 SELECT 后访问 order_header 的查询

第 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;
Copy

现在,将此策略应用到混合表。

ALTER TABLE truck MODIFY COLUMN truck_email
  SET MASKING POLICY hide_column_values USING (truck_email);
Copy

因为您目前使用的是 hybrid_quickstart_role,所以 truck_email 应进行掩码。运行以下查询:

SELECT * FROM truck LIMIT 10;
Copy
不对 truck_email 列进行掩码的查询

切换到 HYBRID_QUICKSTART_BI_USER_ROLE 并再次运行查询。现在,TRUCK_EMAIL 列应进行掩码。

USE ROLE hybrid_quickstart_bi_user_role;
SELECT * FROM truck LIMIT 10;
Copy
对 truck_email 列进行掩码的查询

第 9 步:清理、结论和延伸阅读

清理

要清理 Snowflake 环境,请运行以下 SQL 语句:

USE ROLE hybrid_quickstart_role;
USE WAREHOUSE hybrid_quickstart_wh;
USE DATABASE hybrid_quickstart_db;
USE SCHEMA data;
Copy
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;
Copy

最后,手动删除 Hybrid Tables - QuickStartHybrid Tables - QuickStart Session 2 工作表。

您学到的内容

在本教程中,您学习了如何:

  • 创建并批量加载混合表。

  • 创建并检查 UNIQUE、PRIMARY KEY 和 FOREIGN KEY 约束的执行。

  • 运行依赖于行级锁的并发更新。

  • 在一致的原子事务中运行多语句操作(跨混合表和标准表)。

  • 查询混合表并将其与标准表联接。

  • 验证安全性和治理原则是否适用于混合表和标准表。

语言: 中文