불변성 제약 조건 사용¶
동적 테이블에서 특정 행이 변경되지 않음을 Snowflake에 알리려면 /sql-reference/sql/create-dynamic-table`의 ``IMMUTABLE WHERE` 절 또는 ALTER DYNAMIC TABLE 문을 사용합니다.
불변성은 변경되지 않는 행을 건너뛰어 새로 고침을 더 빠르게 수행합니다. 불변성이 있는 *백필*은 지속적인 성능 이점을 즉시 그리고 지속적으로 제공합니다.
초기 생성: 백필은 계산 비용 없이 과거 데이터를 즉시 복사합니다. 이를 통해 값비싼 초기 새로 고침을 수행할 필요 없이 수년 간의 과거 데이터가 있는 테이블을 즉시 사용할 수 있습니다.
지속적인 새로 고침: 불변성 제약 조건은 향후 새로 고침 중에 백필된 데이터가 다시 처리되지 않도록 보호합니다. 변경 가능한 리전만 새로 고쳐지므로 테이블이 커도 새로 고침 시간이 빠르게 유지됩니다.
개념적 배경은 불변성 제약 조건 이해하기 섹션을 참조하세요.
기본 예제¶
예: 차원 테이블 변경 시 다시 계산 방지¶
차원 테이블에서 행을 업데이트할 때 변경 가능한 기간의 팩트만 다시 처리합니다.
CREATE DYNAMIC TABLE joined_data
TARGET_LAG = '1 minute'
WAREHOUSE = mywh
IMMUTABLE WHERE (timestamp_col < CURRENT_TIMESTAMP() - INTERVAL '1 day')
AS
SELECT F.primary_key primary_key, F.timestamp_col timestamp_col, D.value dim_value
FROM fact_table F
LEFT OUTER JOIN dimension_table D USING (primary_key);
예: 소스 테이블보다 더 오래 데이터 보존¶
구문 분석된 데이터를 스테이징 테이블보다 더 오래 보존하는 동적 테이블을 생성하고 태스크로 이전 스테이징 데이터를 삭제합니다.
CREATE TABLE staging_data (raw TEXT, ts TIMESTAMP);
CREATE DYNAMIC TABLE parsed_data
TARGET_LAG = '1 minute'
WAREHOUSE = mywh
IMMUTABLE WHERE (ts < CURRENT_TIMESTAMP() - INTERVAL '7 days')
AS
SELECT
parse_json(raw):event_id::string event_id,
parse_json(raw):name::string name,
parse_json(raw):region::string region,
ts
FROM staging_data
WHERE region = 'US';
CREATE TASK delete_old_staging_data
WAREHOUSE = mywh
SCHEDULE = '24 hours'
AS
DELETE FROM staging_data WHERE ts < CURRENT_TIMESTAMP() - INTERVAL '30 days';
예: 다운스트림 테이블이 전체 새로 고침 테이블에서 증분 새로 고침을 사용하도록 허용¶
일부 쿼리 구문(예: Python 사용자 정의 테이블 함수)에는 전체 새로 고침 모드가 필요합니다. 불변성 제약 조건을 통해 다운스트림 테이블에서 증분 새로 고침을 계속 사용할 수 있습니다.
CREATE DYNAMIC TABLE udtf_dt
TARGET_LAG = '1 hour'
WAREHOUSE = mywh
REFRESH_MODE = FULL
IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
AS
SELECT ts, data, output, join_key
FROM input_table, TABLE(my_udtf(data));
CREATE DYNAMIC TABLE incremental_join_dt
TARGET_LAG = '1 hour'
WAREHOUSE = mywh
REFRESH_MODE = INCREMENTAL
IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
AS
SELECT * FROM udtf_dt JOIN dim_table USING (join_key);
백필 예제¶
다음 예시에서는 백필된 데이터가 있는 테이블에서 새 동적 테이블을 만드는 방법을 보여줍니다.
백필 테이블에는 동적 테이블과 동일한 순서로 호환되는 데이터 타입이 있는 일치하는 열이 포함되어야 합니다. Snowflake는 백필 테이블에서 테이블 속성 또는 권한을 복사하지 않습니다.
Time Travel AT | BEFORE 매개 변수를 지정하는 경우, Snowflake는 지정된 시간에 백필 테이블에서 데이터를 복사합니다.
불변성 제약 조건 및 백필된 데이터로 작업하는 경우 다음 제한 사항이 적용됩니다.
현재는 일반 및 동적 테이블만 백필에 사용할 수 있습니다.
정책이나 태그는 백필 테이블에서 복사되므로 새 동적 테이블에서 지정할 수 없습니다.
새 동적 테이블과 백필 테이블의 클러스터링 키는 동일해야 합니다.
예: 테이블의 일부에서 백필¶
다음 예시에서는 :code:`my_backfill_table`에서 :code:`my_dynamic_table`의 변경 불가능한 리전을 백필하고 동적 테이블 정의에서 변경 가능한 리전을 백필합니다.
이 동적 테이블을 다시 초기화하는 경우 다음을 수행합니다.
증분 새로 고침 모드: Snowflake는 변경 가능한 모든 행을 삭제하고 변경 가능한 리전만 다시 채웁니다.
전체 새로 고침 모드: Snowflake는 동일한 효과로 전체 새로 고침을 수행합니다.
CREATE DYNAMIC TABLE my_dynamic_table (day TIMESTAMP, totalSales NUMBER)
IMMUTABLE WHERE (day < '2025-01-01')
BACKFILL FROM my_backfill_table
TARGET_LAG = '20 minutes'
WAREHOUSE = 'mywh'
AS SELECT DATE_TRUNC('day', ts) AS day, sum(price)
FROM my_base_table
GROUP BY day;
예: 백필을 사용하여 동적 테이블의 데이터 복구 또는 수정¶
동적 테이블의 데이터 또는 정의는 직접 편집할 수 없습니다. 데이터를 복구하거나 수정하려면 다음 해결 방법 단계를 완료합니다.
동적 테이블을 일반 테이블로 복제합니다.
필요에 따라 복제된 테이블을 수정합니다.
편집된 테이블에서 새 동적 테이블로 백필합니다.
다음 예시에서 my_dynamic_table`은 :code:`sales 기본 테이블에서 일일 판매 데이터를 집계합니다.
CREATE OR REPLACE TABLE sales(item_id INT, ts TIMESTAMP, sales_price FLOAT);
INSERT INTO sales VALUES (1, '2025-05-01 01:00:00', 10.0), (1, '2025-05-01 02:00:00', 15.0), (1, '2025-05-01 03:00:00', 11.0);
INSERT INTO sales VALUES (1, '2025-05-02 00:00:00', 11.0), (1, '2025-05-02 05:00:00', 13.0);
CREATE DYNAMIC TABLE my_dynamic_table
TARGET_LAG = 'DOWNSTREAM'
WAREHOUSE = mywh
INITIALIZE = on_create
IMMUTABLE WHERE (day <= '2025-05-01')
AS
SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count FROM sales
GROUP BY item_id, day;
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
+---------+------------+-------------+
| ITEM_ID | DAY | SALES_COUNT |
|---------+------------+-------------|
| 1 | 2025-05-01 | 3 |
| 1 | 2025-05-02 | 2 |
+---------+------------+-------------+
필요에 따라 이전 데이터를 아카이브하여 저장소 비용을 절감할 수 있습니다.
DELETE FROM sales WHERE ts < '2025-05-02';
ALTER DYNAMIC TABLE my_dynamic_table REFRESH;
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
나중에 :code:`2025-05-01`에서 판매 오류를 발견하게 되는데, 여기서 :code:`sales_count`는 2여야 합니다. 이 문제를 수정하려면 다음을 수행합니다.
:code:`my_dynamic_table`을 일반 테이블에 복제합니다.
CREATE OR REPLACE TABLE my_dt_clone_table CLONE my_dynamic_table;
복제된 테이블을 업데이트합니다.
UPDATE my_dt_clone_table SET sales_count = 2 WHERE day = '2025-05-01'; SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dt_clone_table;
+---------+------------+-------------+ | ITEM_ID | DAY | SALES_COUNT | |---------+------------+-------------| | 1 | 2025-05-01 | 2 | | 1 | 2025-05-02 | 2 | +---------+------------+-------------+
편집된 복제본을 백필 소스로 사용하여 동적 테이블을 다시 생성합니다.
CREATE OR REPLACE DYNAMIC TABLE my_dynamic_table BACKFILL FROM my_dt_clone_table IMMUTABLE WHERE (day <= '2025-05-01') TARGET_LAG = 'DOWNSTREAM' WAREHOUSE = mywh INITIALIZE = on_create AS SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count FROM sales GROUP BY item_id, day;
이 접근 방식을 사용하면 기본 테이블을 수정하지 않고도 동적 테이블의 데이터를 복구하거나 수정할 수 있습니다.
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
+---------+------------+-------------+ | ITEM_ID | DAY | SALES_COUNT | |---------+------------+-------------| | 1 | 2025-05-01 | 2 | | 1 | 2025-05-02 | 2 | +---------+------------+-------------+
예: 백필을 사용하여 동적 테이블의 스키마 수정하기¶
동적 테이블의 스키마는 직접 변경할 수 없습니다. 예를 들어, 열을 추가하는 등 스키마를 업데이트하려면 다음 단계를 따릅니다.
동적 테이블을 일반 테이블로 복제합니다. 다음 예제에서는
sales`(:ref:`상기 <label-data-surgery-example>)에서 생성된 :code:`my_dynamic_table`을 사용합니다.CREATE OR REPLACE TABLE my_dt_clone_table CLONE my_dynamic_table;
복제된 테이블의 스키마를 수정합니다.
ALTER TABLE my_dt_clone_table ADD COLUMN sales_avg FLOAT; SELECT item_id, to_char(day, 'YYYY-MM-DD') as DAY, SALES_COUNT, SALES_AVG FROM my_dt_clone_table;
선택적으로, 새 열에 데이터를 추가합니다.
편집된 복제본을 백필 소스로 사용하여 동적 테이블을 다시 생성합니다.
CREATE OR REPLACE DYNAMIC TABLE my_dynamic_table BACKFILL FROM my_dt_clone_table IMMUTABLE WHERE (day <= '2025-05-01') TARGET_LAG = 'DOWNSTREAM' WAREHOUSE = mywh INITIALIZE = on_create AS SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count, avg(sales_price) as sales_avg FROM sales GROUP BY item_id, day;
동적 테이블에 새 열이 나타나는지 확인합니다.
SELECT item_id, to_char(day, 'YYYY-MM-DD') as DAY, SALES_COUNT, SALES_AVG, metadata$is_immutable as IMMUTABLE from my_dynamic_table ORDER BY ITEM_ID, DAY;
+---------+------------+-------------+-----------+-----------+ | ITEM_ID | DAY | SALES_COUNT | SALES_AVG | IMMUTABLE | |---------+------------+-------------|-----------|-----------| | 1 | 2025-05-01 | 3 | NULL | TRUE | | 1 | 2025-05-02 | 2 | 12 | FALSE | +---------+-------------+------------+-----------+-----------+
불변성 상태 확인¶
동적 테이블에서 행을 변경할 수 있는지 확인하려면 METADATA$IS_IMMUTABLE 열을 쿼리합니다.
SELECT *, METADATA$IS_IMMUTABLE FROM my_dynamic_table;
동적 테이블의 불변성 제약 조건을 확인하려면 /sql-reference/sql/show-dynamic-tables`를 실행하고 ``immutable_where` 열을 확인합니다.