하이브리드 테이블 시작하기¶
소개¶
하이브리드 테이블 은 하이브리드 트랜잭션 및 분석 워크로드에 최적화된 Snowflake 테이블 유형입니다. 이러한 워크로드에는 테이블의 단일 행에 액세스하는 소규모의 무작위 읽기 및 쓰기에서 낮은 지연 시간과 높은 처리량이 필요합니다. 하이브리드 테이블은 트랜잭션 워크로드에 중요한 고유성 및 참조 무결성 제약 조건을 적용합니다.
하이브리드 테이블을 다른 Snowflake 테이블 및 기능과 함께 사용하여 트랜잭션 및 분석 데이터를 단일 플랫폼에 통합하는 Unistore 워크로드 를 강화할 수 있습니다.
하이브리드 테이블은 기존 Snowflake 아키텍처에 완벽하게 통합됩니다. 고객은 동일한 Snowflake 데이터베이스 서비스에 연결합니다. 쿼리는 클라우드 서비스 계층에서 컴파일 및 최적화되고 가상 웨어하우스의 동일한 쿼리 엔진에서 실행됩니다. 이 아키텍처는 여러 가지 주요 이점을 제공합니다.
데이터 거버넌스와 같은 Snowflake 플랫폼 기능은 기본적으로 하이브리드 테이블에서 작동합니다.
연산 쿼리와 분석 쿼리를 혼합한 하이브리드 워크로드를 실행할 수 있습니다.
하이브리드 테이블을 다른 Snowflake 테이블과 조인할 수 있으며 쿼리는 동일한 쿼리 엔진에서 기본적이고 효율적으로 실행됩니다. 페더레이션이 필요하지 않습니다.
하이브리드 테이블과 기타 Snowflake 테이블에서 원자성 트랜잭션을 실행할 수 있습니다. 자체적으로 2단계 커밋을 오케스트레이션할 필요가 없습니다.

하이브리드 테이블은 행 저장소를 기본 데이터 저장소로 활용하여 탁월한 운영 쿼리 성능을 제공합니다. 하이브리드 테이블에 쓰면 데이터가 행 저장소에 직접 기록됩니다. 진행 중인 운영 워크로드에 영향을 주지 않고 대규모 스캔에 대해 더 나은 성능과 워크로드 격리를 제공하기 위해 데이터가 오브젝트 저장소에 비동기식으로 복사됩니다. 일부 데이터는 분석 쿼리에 대한 더 나은 성능을 제공하기 위해 웨어하우스에 열 형식으로 캐시될 수도 있습니다. 논리 하이브리드 테이블에 대해 SQL 문을 실행하기만 하면 쿼리 최적화 도구가 최상의 성능을 제공하기 위해 데이터를 읽을 위치를 결정합니다. 기본 인프라에 대해 걱정할 필요 없이 데이터에 대해 일관된 뷰가 1개 생성됩니다.
알아볼 내용¶
이 자습서에서는 다음에 대해 설명합니다.
하이브리드 테이블을 생성하고 대량으로 로드합니다.
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단계. 3개의 테이블 생성 및 대량 로드¶
이 자습서에서는 Tasty Bytes Snowflake라는 가상의 푸드트럭 사업을 사용하여 애플리케이션에 데이터를 제공하는 사용 사례를 시뮬레이션합니다.
3개의 테이블을 생성합니다.
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 <테이블> 또는 INSERT INTO … SELECT 사용). CTAS 문을 사용하여 하이브리드 테이블에 데이터를 대량 로드하는 것은 테이블 생성의 일부로 데이터를 로드할 때만 적용할 수 있는 몇 가지 최적화가 있기 때문에 적극 권장됩니다.
Snowflake 테이블에 액세스하거나 로드할 수 있는 스테이징된 데이터 세트를 설명하는 파일 형식 과 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 문은 INSERT INTO … SELECT 문을 사용하여 order_header
테이블에 데이터를 삽입합니다.
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 <오브젝트> 명령을 사용하여 테이블의 열에 대한 정보를 표시합니다. 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가 이미 존재하지 않는 경우 100
ID 이 있는 제품의 판매는 판매 정보 테이블에 기록할 수 없습니다.
두 가지 유형의 제약 조건 모두 안정적이면서도 빠른 트랜잭션 처리에 크게 의존하는 애플리케이션의 데이터 정확성과 일관성을 지원합니다.
4.1단계. UNIQUE 제약 조건 테스트¶
UNIQUE 제약 조건은 열의 모든 값이 서로 다르도록 합니다. truck
테이블에서 truck_email
열을 NOT NULL 및 UNIQUE로 정의했습니다.
UNIQUE 제약 조건이 제공된 경우 동일한 이메일 주소를 가진 두 개의 레코드를 삽입하려고 하면 문이 실패합니다. 이 동작을 테스트하려면 다음 명령을 실행합니다.
먼저 기존 이메일 주소를 선택하고 해당 문자열에 변수 truck_email
을 설정합니다. 그런 다음 테이블에서 truck_id
의 최대값을 선택하고 다른 변수 max_truck_id
를 해당 값으로 설정합니다. 다음으로 max_truck_id
를 1씩 증가시키는 세 번째 변수 new_truck_id
를 설정합니다. 이 프로세스를 수행하면 새 행을 삽입할 때 “Primary key already exists” 오류가 발생하지 않습니다.
마지막으로 새로운 행을 삽입합니다.
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 에서 Snowsight 의 오른쪽 상단에 있는 + 버튼을 클릭한 다음 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단계. 마스킹 정책 만들기 및 구현¶
이 단계에서는 마스킹 정책 을 생성하고 ALTER TABLE … ALTER COLUMN 문을 사용하여 truck
하이브리드 테이블의 truck_email
열에 적용합니다. 마스킹 정책은 역할과 권한이 다른 사용자에게 데이터의 열 수준 공개를 제어하는 표준 방법입니다.
참고
마스킹 정책을 생성하려면 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 제약 조건의 적용을 생성하고 확인합니다.
행 수준 잠금에 따라 동시 업데이트를 실행합니다.
일관된 원자 트랜잭션(하이브리드 및 표준 테이블)에서 다중 문 작업을 실행합니다.
하이브리드 테이블을 쿼리하여 표준 테이블에 조인합니다.
보안 및 거버넌스 원칙이 하이브리드 테이블과 표준 테이블 모두에 적용되는지 확인합니다.