다이나믹 테이블 리프레시 문제 해결하기

다이나믹 테이블 리프레시 문제 해결하기

다이나믹 테이블 리프레시 문제를 진단하고 해결하는 방법을 알려드릴게요. 생성 시점 문제는 다이나믹 테이블 생성 문제 해결을, 권한 관련 실패는 다이나믹 테이블 권한 문제 해결을 참고하세요.

출처: Snowflake 문서

본문

아래 빠른 상태 점검(quick health check)부터 실행해 보세요. 여기서 증상이 안 보이면 섹션 제목을 훑어 일치하는 항목을 찾으세요. 느린 리프레시 진단은 증분 리프레시 쿼리 최적화를 참고하세요.

-- 빠른 상태 점검: 실패, 일시 중단, 지연 중인 다이나믹 테이블 찾기
SHOW DYNAMIC TABLES;
SELECT "name", "scheduling_state", "refresh_mode", "target_lag",
       DATEDIFF('minute', "data_timestamp", CURRENT_TIMESTAMP()) AS actual_lag_minutes
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
ORDER BY actual_lag_minutes DESC NULLS FIRST;
+-------------------+-------------------+--------------+------------+---------------------+
| name              | scheduling_state  | refresh_mode | target_lag | actual_lag_minutes  |
+-------------------+-------------------+--------------+------------+---------------------+
| dt_orders_daily   | SUSPENDED         | INCREMENTAL  | 30 minutes | NULL                |
| dt_orders         | RUNNING           | INCREMENTAL  | 10 minutes | 12                  |
+-------------------+-------------------+--------------+------------+---------------------+

Snowsight의 Refresh History 탭에서도 리프레시 상태를 볼 수 있어요. <C>scheduling_state</C>가 RUNNING이 아니거나 <C>actual_lag_minutes</C>가 target lag를 크게 초과하는 행을 찾으세요. 이 쿼리가 행을 반환하지 않으면 권한 문제 해결을 참고해 역할의 권한을 확인하세요.

여기에 나열되지 않은 문제를 만나면 Snowflake Support에 문의하세요.

UPSTREAM_FAILED 상태로 리프레시 실패

다이나믹 테이블이 리프레시에 실패한 다른 다이나믹 테이블에 의존하면, 다운스트림 테이블은 UPSTREAM_FAILED를 보고합니다. 근본 원인은 항상 상위에 있어요.

  • UPSTREAM_FAILED를 보이는 다이나믹 테이블을 찾으세요:
SELECT name, state, state_code, state_message, refresh_start_time
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(NAME_PREFIX => 'mydb.myschema'))
WHERE state IN ('FAILED', 'UPSTREAM_FAILED')
ORDER BY refresh_start_time DESC
LIMIT 20;
+---------------------+---------+-----------------+------------------------------------------+-------------------------+
| NAME                | STATE   | STATE_CODE      | STATE_MESSAGE                            | REFRESH_START_TIME      |
+---------------------+---------+-----------------+------------------------------------------+-------------------------+
| DT_ORDERS_DAILY     | FAILED  | UPSTREAM_FAILED | Some inputs failed to refresh: [STG_O... | 2025-01-16 12:00:00.000 |
| DT_ORDERS           | FAILED  | USER_ERROR      | SQL compilation error: invalid ident...  | 2025-01-16 11:59:45.000 |
+---------------------+---------+-----------------+------------------------------------------+-------------------------+
  • 실패한 상위 테이블을 직접 지목하는 <C>state_message</C> 컬럼을 읽으세요. 이 예에서 <C>dt_orders</C>는 <C>USER_ERROR</C>를 가지며, 이는 자기 정의에 문제가 있다는 뜻입니다. 그 실패가 <C>dt_orders_daily</C>로 연쇄됩니다.
  • 또는 Snowsight의 Graph 뷰를 열어 파이프라인을 시각화하세요. Transformation > Dynamic tables로 이동해 파이프라인의 아무 테이블이나 선택하고 Graph 탭으로 전환하세요. 실패한 상위 테이블이 강조 표시됩니다.
  • 근본 원인 테이블을 먼저 고치세요. 상위 테이블이 성공적으로 리프레시된 후, 다운스트림의 UPSTREAM_FAILED 테이블은 다음 예약 리프레시 때 자동으로 회복됩니다.

다이나믹 테이블이 일시 중단됨

일시 중단된 다이나믹 테이블은 완전히 리프레시를 멈춥니다. 재개할 때까지 새 리프레시가 시도되지 않아요.

  • 스케줄링 상태와 중단 사유를 확인하세요:
SHOW DYNAMIC TABLES LIKE 'dt_orders' IN SCHEMA mydb.myschema;
+------------+-------------------+-----------+
| name       | scheduling_state  | ...       |
+------------+-------------------+-----------+
| DT_ORDERS  | SUSPENDED         | ...       |
+------------+-------------------+-----------+
  • 왜 일시 중단됐는지 확인하세요. 스케줄링 상태를 조회해 사유 코드를 보세요:
SELECT name,
       scheduling_state:state::STRING AS state,
       scheduling_state:reason_code::STRING AS reason_code,
       scheduling_state:reason_message::STRING AS reason_message
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_GRAPH_HISTORY())
WHERE name = 'DT_ORDERS'
ORDER BY valid_from DESC
LIMIT 1;

가장 흔한 원인은 수동 일시 중단(<C>USER_SUSPENDED</C>), 연속 5회 예약 리프레시 실패(<C>SUSPENDED_DUE_TO_ERRORS</C>), 그리고 일시 중단된 상위 테이블에서의 연쇄(<C>UPSTREAM_USER_SUSPENDED</C> 또는 <C>UPSTREAM_SUSPENDED_DUE_TO_ERRORS</C>)입니다. 전체 중단 사유 코드 목록과 재개 연쇄 동작은 다이나믹 테이블 관리를 참고하세요.

  • 근본 원인을 고친 뒤(예: 다이나믹 테이블 정의에서 컬럼명 수정) 재개하세요:
ALTER DYNAMIC TABLE mydb.myschema.dt_orders RESUME;

다이나믹 테이블을 재개하면 연쇄 효과로 일시 중단됐던 다운스트림 테이블(사유가 <C>UPSTREAM_USER_SUSPENDED</C>나 <C>UPSTREAM_SUSPENDED_DUE_TO_ERRORS</C>인 테이블)도 자동으로 재개됩니다. 수동으로 일시 중단한 테이블은 각각 개별적으로 재개해야 해요. 재개는 스케줄 가능 상태를 복원하지만 즉시 리프레시를 트리거하지는 않습니다.

오류로 리프레시 실패

원인과 해결책을 포함한 전체 리프레시 오류 코드 목록은 다이나믹 테이블 오류 코드 레퍼런스를 참고하세요. 그 페이지를 오류 메시지나 오류 코드로 검색할 수 있어요. 오류 메시지에 <C>query_id</C>가 포함되면 Snowsight에서 쿼리 프로필을 열어 리소스 사용량을 보고 병목을 식별하세요. 실행 시간 살펴보기를 참고하세요.

기본 테이블 스키마 변경 후 리프레시 실패

기본 테이블에서 다이나믹 테이블 정의가 참조하는 컬럼이 삭제되거나 이름이 바뀌면 리프레시가 실패합니다. 다이나믹 테이블은 스키마 진화(schema evolution)와 함께 <C>SELECT *</C>를 사용하지 않는 한 스키마 변경에 자동으로 적응할 수 없어요(다이나믹 테이블 수정를 참고하세요).

  • 스키마 관련 오류가 있는 최근 리프레시 실패를 확인하세요:
SELECT name, state, state_message
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(
  NAME_PREFIX => 'mydb.myschema.dt_orders',
  ERROR_ONLY => TRUE))
ORDER BY refresh_start_time DESC
LIMIT 1;
+------------+---------+--------------------------------------------------------------+
| NAME       | STATE   | STATE_MESSAGE                                                |
+------------+---------+--------------------------------------------------------------+
| DT_ORDERS  | FAILED  | SQL compilation error: invalid identifier 'ORDER_STATUS'     |
+------------+---------+--------------------------------------------------------------+
  • 스키마 변경을 식별하세요. 다이나믹 테이블의 정의를 현재 기본 테이블 스키마와 비교하세요:
-- 다이나믹 테이블의 정의 보기
SELECT GET_DDL('DYNAMIC_TABLE', 'mydb.myschema.dt_orders');

-- 기본 테이블의 현재 컬럼 보기
DESCRIBE TABLE mydb.myschema.raw_orders;

GET_DDL 출력에서 DESCRIBE 출력에 없는 컬럼 이름을 찾으세요.

-- GET_DDL은 정의가 order_status를 참조함을 보여 줌
-- DESCRIBE TABLE은 컬럼이 status로 이름이 바뀌었음을 보여 줌
+---------------+-------------------+
| name          | type              |
+---------------+-------------------+
| ORDER_ID      | NUMBER(38,0)      |
| CUSTOMER_ID   | NUMBER(38,0)      |
| ORDER_DATE    | DATE              |
| PRODUCT_NAME  | VARCHAR(16777216) |
| QUANTITY      | NUMBER(38,0)      |
| UNIT_PRICE    | NUMBER(10,2)      |
| STATUS        | VARCHAR(16777216) |
+---------------+-------------------+
  • 불일치를 해결하세요. 기본 테이블에서 삭제된 컬럼을 복원하거나, 올바른 컬럼을 참조하는 업데이트된 정의로 다이나믹 테이블을 다시 만드세요.

팁 다이나믹 테이블이 명시적 컬럼 목록을 사용하고 기본 테이블 스키마 변경이 리프레시 실패를 일으키면, 자동 스키마 진화를 위해 <C>SELECT *</C> 또는 <C>SELECT * EXCLUDE (...)</C>로 전환하는 것을 고려하세요. 자세한 내용은 다이나믹 테이블 수정을 참고하세요.

dbt 또는 CREATE OR REPLACE가 change tracking을 깨뜨림

기본 테이블이 <C>CREATE OR REPLACE</C>로 교체되면 새 테이블은 다른 객체입니다. 다이나믹 테이블은 원래 테이블의 change tracking 기록에 대한 참조를 잃어 증분 리프레시가 실패합니다.

  • change-tracking 오류에 대해 리프레시 기록을 확인하세요:
SELECT name, state, state_message
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(
  NAME_PREFIX => 'mydb.myschema.dt_orders',
  ERROR_ONLY => TRUE))
ORDER BY refresh_start_time DESC
LIMIT 5;

구체적인 오류는 무엇이 바뀌었는지에 따라 달라져요. change tracking만 유실됐다면(스키마 동일) 다음과 같이 보입니다:

Change tracking is not enabled or has been missing for the time range requested on table <TABLE>.

스키마도 바뀌었다면:

Base TABLE <TABLE> dropped, cannot read from stream on it.
  • dbt나 <C>CREATE OR REPLACE TABLE</C>을 실행하는 다른 도구를 쓴다면 다음 우회 방법 중 하나를 사용하세요.

옵션 A: DDL 변경 주변에서 SUSPEND와 RESUME 사용

일시 중단하면 DDL 창 동안의 실패를 막을 수 있어요. 다이나믹 테이블은 재개 후에도 재초기화되지만, 일시적인 실패를 피하고 타이밍을 제어할 수 있습니다.

-- dbt 실행 전
ALTER DYNAMIC TABLE mydb.myschema.dt_orders SUSPEND;

-- dbt 실행

-- dbt 완료 후
ALTER DYNAMIC TABLE mydb.myschema.dt_orders RESUME;

옵션 B: 교체 후 change tracking 재활성화

도구가 <C>CREATE OR REPLACE</C>를 써야 한다면, change tracking을 다시 활성화하는 post-hook을 추가하세요:

ALTER TABLE mydb.myschema.raw_orders SET CHANGE_TRACKING = TRUE;

또는 <C>CREATE OR REPLACE TABLE</C> 문에 <C>CHANGE_TRACKING = TRUE</C>를 직접 포함하세요.

옵션 C: <C>CREATE OR REPLACE</C> 대신 <C>INSERT OVERWRITE</C> 사용

<C>INSERT OVERWRITE</C>는 테이블 객체와 그 change tracking 기록을 보존합니다:

INSERT OVERWRITE INTO mydb.myschema.raw_orders
SELECT * FROM mydb.myschema.raw_orders_staging;
  • 우회 방법을 적용한 뒤, 일시 중단됐었다면 다이나믹 테이블을 재개하세요:
ALTER DYNAMIC TABLE mydb.myschema.dt_orders RESUME;

다이나믹 테이블이 예상치 못하게 재초기화됨

재초기화는 다이나믹 테이블이 평소 증분 리프레시를 사용하더라도 전체 테이블을 처음부터 다시 처리하도록 강제합니다. 이는 일반 리프레시보다 더 비싸고, 다이나믹 테이블에 의존하는 스트림에 큰 변경 세트를 만들어 냅니다. 다이나믹 테이블의 스트림은 재초기화를 넘겨 살아남지만, 다음 읽기는 전체 테이블을 변경으로 반환합니다. 이 큰 변경 세트 처리를 피하고 오프셋을 리셋하려면 스트림을 다시 만드세요. 재초기화 후 다이나믹 테이블 스트림이 큰 변경 세트를 반환을 참고하세요.

  • <C>refresh_action</C> 컬럼을 확인해 재초기화가 일어났는지 확인하세요:
SELECT name, refresh_action, refresh_trigger, state, refresh_start_time
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(NAME_PREFIX => 'mydb.myschema.dt_orders'))
ORDER BY refresh_start_time DESC
LIMIT 5;
+------------+----------------+-----------------+-----------+-------------------------+
| NAME       | REFRESH_ACTION | REFRESH_TRIGGER | STATE     | REFRESH_START_TIME      |
+------------+----------------+-----------------+-----------+-------------------------+
| DT_ORDERS  | REINITIALIZE   | CREATION        | SUCCEEDED | 2025-01-16 12:00:00.000 |
| DT_ORDERS  | INCREMENTAL    | SCHEDULED       | SUCCEEDED | 2025-01-16 11:50:00.000 |
+------------+----------------+-----------------+-----------+-------------------------+
  • 트리거를 식별하세요. 가장 흔한 원인은 다이나믹 테이블 자체의 <C>CREATE OR REPLACE</C>(리프레시 기록에서 <C>refresh_trigger = CREATION</C>으로 나타남) 또는 상위 기본 테이블의 그것, 그리고 다이나믹 테이블이 참조하는 기본 테이블의 스키마 변경(컬럼 삭제·이름 변경)입니다. 전체 재초기화 트리거 목록은 다이나믹 테이블 수정을 참고하세요.
  • 재초기화 시점을 제어하고 DDL 변경(예: dbt 실행) 중 리프레시 실패를 피하려면, DDL 전에 다이나믹 테이블을 일시 중단하고 후에 재개하세요. 다이나믹 테이블은 재개 후 초기 리프레시에서 여전히 재초기화되지만, 일시적인 실패를 피하고 타이밍을 제어할 수 있어요:
-- 기본 테이블에서 DDL 실행 전
ALTER DYNAMIC TABLE mydb.myschema.dt_orders SUSPEND;

-- DDL 실행 (dbt run, CREATE OR REPLACE, 스키마 변경)

-- DDL 완료 후
ALTER DYNAMIC TABLE mydb.myschema.dt_orders RESUME;

재초기화에 대한 자세한 내용은 재초기화 트리거를 참고하세요.

재초기화 후 다이나믹 테이블 스트림이 큰 변경 세트를 반환

다이나믹 테이블이 재초기화되면 데이터 전체가 다시 처리됩니다. 재초기화 후 스트림은 마지막 읽기 오프셋과 재초기화된 출력 사이의 모든 행 수준 차이를 노출합니다. 새 출력의 모든 행은 INSERT로, 이전 버전의 모든 행은 DELETE로 나타납니다. 이는 아주 큰 변경 세트를 만들 수 있어요. 자세한 내용은 다이나믹 테이블에 스트림 사용을 참고하세요.

  • 다이나믹 테이블이 최근에 재초기화됐는지 확인하세요:
SELECT name, refresh_action, refresh_trigger, refresh_start_time
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(NAME_PREFIX => 'mydb.myschema.dt_orders'))
WHERE refresh_action = 'REINITIALIZE'
ORDER BY refresh_start_time DESC
LIMIT 1;
+------------+----------------+-----------------+-------------------------+
| NAME       | REFRESH_ACTION | REFRESH_TRIGGER | REFRESH_START_TIME      |
+------------+----------------+-----------------+-------------------------+
| DT_ORDERS  | REINITIALIZE   | CREATION        | 2025-01-16 12:00:00.000 |
+------------+----------------+-----------------+-------------------------+
  • 오프셋을 다이나믹 테이블의 현재 상태로 리셋하려면 스트림을 다시 만드세요:
CREATE OR REPLACE STREAM mydb.myschema.dt_orders_stream
    ON DYNAMIC TABLE mydb.myschema.dt_orders;
  • 재발을 막으려면 재초기화를 최소화하세요. 예상치 못한 다이나믹 테이블 재초기화를 참고하세요.
  • 재초기화 후 다운스트림 소비자가 처리해야 하는 변경량을 줄이려면 다이나믹 테이블에 RELY 기본 키(primary key)를 추가하세요. Snowflake는 다운스트림 다이나믹 테이블과 스트림에 대해 일치하는 INSERT/DELETE 쌍을 UPDATE로 병합합니다.

다이나믹 테이블의 스트림에 대한 자세한 내용은 다이나믹 테이블에 스트림 사용을 참고하세요.

INCREMENTAL을 기대했는데 다이나믹 테이블이 FULL로 리프레시됨

<C>REFRESH_MODE = AUTO</C>로 생성된 다이나믹 테이블은 해석된 모드가 영구적이며 ALTER로 변경할 수 없어요. AUTO가 해석하는 방식과 해석된 모드를 확인하는 법은 다이나믹 테이블 리프레시 모드를 참고하세요.

증분 리프레시가 필요하다면 정의를 고치고 <C>CREATE OR REPLACE DYNAMIC TABLE ... REFRESH_MODE = INCREMENTAL</C>로 다이나믹 테이블을 다시 만들어 생성 시점에 검증을 강제하세요.

행 액세스 정책 또는 마스킹 정책이 증분 리프레시를 막을 수 있음

기본 테이블의 행 액세스·마스킹 정책은 어떤 함수를 사용하는지에 따라 증분 리프레시를 막을 수 있어요. 지원되는 조합은 다이나믹 테이블 지원 쿼리를 참고하세요.

일반적인 오류 메시지:

Query contains context functions on which change tracking is not supported.
Incremental refresh is not supported for queries referencing tables with row access policies
that use context functions.
  • 행 액세스·마스킹 정책이 있는 기본 테이블을 식별하세요:
-- 행 액세스 정책 확인
SELECT * FROM TABLE(INFORMATION_SCHEMA.POLICY_REFERENCES(
  REF_ENTITY_NAME => 'mydb.myschema.raw_orders',
  REF_ENTITY_DOMAIN => 'TABLE'));
  • 해결 옵션: 옵션 A: FULL 리프레시 모드로 전환. 전체 리프레시는 매 리프레시마다 전체 쿼리를 처음부터 평가하므로 정책의 컨텍스트 함수가 올바르게 작동합니다:
CREATE OR REPLACE DYNAMIC TABLE mydb.myschema.dt_orders
    TARGET_LAG = '30 minutes'
    WAREHOUSE = transform_wh
    REFRESH_MODE = FULL
AS
SELECT order_id, customer_id, order_date
FROM mydb.myschema.raw_orders;

옵션 B: 정책을 다이나믹 테이블에 적용. 기본 테이블에서 정책을 제거하고 다이나믹 테이블에 적용하세요. 정책이 쿼리 시점(리프레시 시점이 아님)에 실행되므로 컨텍스트 함수가 올바르게 작동합니다:

ALTER TABLE mydb.myschema.raw_orders
    DROP ROW ACCESS POLICY my_policy;

ALTER DYNAMIC TABLE mydb.myschema.dt_orders
    ADD ROW ACCESS POLICY my_policy ON (customer_id);

증분 모드에서 IS_ROLE_IN_SESSION()은 상수 인자만 허용함

다이나믹 테이블이 증분 리프레시를 사용하고 정의가 <C>IS_ROLE_IN_SESSION()</C>을 호출하는 행 액세스 정책이 있는 기본 테이블을 참조하면, 정책 함수는 상수 문자열 인자만 사용해야 합니다. 변수나 컬럼 기반 인자는 증분 모드에서 지원되지 않아요.

IS_ROLE_IN_SESSION() with non-constant arguments is not supported for incremental refresh.
  • 행 액세스 정책 정의를 확인해 <C>IS_ROLE_IN_SESSION()</C>이 어떻게 호출되는지 보세요:
SELECT GET_DDL('POLICY', 'mydb.myschema.my_policy');
  • 정책이 인자로 컬럼 참조를 사용한다면(예: <C>IS_ROLE_IN_SESSION(allowed_role)</C>), 이는 증분 모드에서 지원되지 않습니다.

  • 해결 옵션:

    • 정책을 상수 역할 이름(<C>IS_ROLE_IN_SESSION('ANALYST_ROLE')</C>)으로 다시 작성하세요.
    • 정책을 기본 테이블에서 다이나믹 테이블로 옮기세요. 그러면 리프레시 시점이 아니라 쿼리 시점에 실행됩니다.
    • 다이나믹 테이블을 <C>REFRESH_MODE = FULL</C>로 전환하세요.

프로젝션 정책이 예상치 못한 리프레시 동작을 일으킴

기본 테이블 컬럼의 프로젝션 정책은 다이나믹 테이블 리프레시 동작에 영향을 줄 수 있어요. 프로젝션 정책이 정의가 참조하는 컬럼을 제한하면, 리프레시는 마스킹된 데이터를 보거나(잘못된 출력 생성) 소유자 역할이 정책의 허용 목록에 없을 때 바로 실패합니다.

  • 기본 테이블에 프로젝션 정책이 있는지 확인하세요:
SELECT * FROM TABLE(INFORMATION_SCHEMA.POLICY_REFERENCES(
  REF_ENTITY_NAME => 'mydb.myschema.raw_orders',
  REF_ENTITY_DOMAIN => 'TABLE'))
WHERE policy_kind = 'PROJECTION_POLICY';
  • 다이나믹 테이블의 소유자 역할이 프로젝션 정책의 허용 목록에 없으면 리프레시가 마스킹되거나 제한된 데이터를 봅니다. 소유자 역할에 적절한 액세스를 부여하거나 프로젝션 정책을 수정하세요:
-- 옵션: 프로젝션 정책에서 소유자 역할이 승인되었는지 확인

-- 프로젝션 정책 정의를 확인하고 소유자 역할을 포함하도록 업데이트
  • 다이나믹 테이블에 마스킹되지 않은 데이터를 담고 싶다면(다운스트림 소비는 별도 액세스 제어로), 프로젝션 정책을 통해 소유자 역할이 전체 액세스를 갖도록 하세요.

RESUME 후 다이나믹 테이블이 리프레시되지 않음

<C>ALTER DYNAMIC TABLE ... RESUME</C>을 실행한 뒤에도 리프레시가 즉시 트리거되지 않을 수 있어요. 다이나믹 테이블이 target lag를 초과했다면 다음을 조사하세요.

  • 스케줄링 상태가 RUNNING으로 바뀌었는지 확인하세요:
SHOW DYNAMIC TABLES LIKE 'dt_orders' IN SCHEMA mydb.myschema;
+------------+-------------------+
| name       | scheduling_state  |
+------------+-------------------+
| DT_ORDERS  | RUNNING           |
+------------+-------------------+
  • 증분 리프레시는 time-travel 데이터에 의존합니다. 다이나믹 테이블이 DATA_RETENTION_TIME_IN_DAYS 설정(기본값: Standard Edition은 1일, Enterprise Edition 이상은 최대 90일까지 구성 가능, 명시적으로 설정하지 않으면 데이터베이스·스키마에서 상속)보다 길게 일시 중단됐다면 이 데이터가 만료되어 증분 리프레시가 과거 변경 데이터를 찾을 수 없어요. 리프레시는 다음과 같이 실패합니다:
Time travel data is not available for table <TABLE>.
The requested time is either beyond the allowed time travel period
or before the object creation time.

이 경우 다이나믹 테이블을 다시 만들어야 해요. 재생성 전에 <C>SELECT GET_DDL('DYNAMIC_TABLE', 'mydb.myschema.dt_orders')</C>를 사용해 기존 정의를 포착하세요. 다운스트림 다이나믹 테이블도 재생성 후 재초기화됩니다. 과거 데이터를 재처리하지 않고 다이나믹 테이블을 재생성하려면 BACKFILL FROM으로 다이나믹 테이블 시드를 참고하세요.

  • 스케줄링 상태가 RUNNING인데 기록에 리프레시가 나타나지 않으면, 수동 리프레시를 트리거해 다이나믹 테이블이 리프레시할 수 있는지 확인하세요:
ALTER DYNAMIC TABLE mydb.myschema.dt_orders REFRESH;

일시 중단 중에 웨어하우스가 삭제되거나 다시 할당됐다면 오류로 리프레시 실패의 웨어하우스 오류를 참고하세요.

예약 리프레시가 건너뛰어지고 있음

건너뛴 리프레시(skipped refresh)는 Snowflake가 예약된 리프레시를 실행하지 않기로 선택했음을 의미합니다. 다이나믹 테이블의 데이터는 진행되지 않지만 오류는 보고되지 않아요.

  • 리프레시 기록에서 건너뛴 리프레시를 확인하세요:
SELECT name, state, state_code, state_message, data_timestamp
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(NAME_PREFIX => 'mydb.myschema.dt_orders'))
WHERE state = 'SKIPPED'
ORDER BY refresh_start_time DESC
LIMIT 10;
+------------+---------+-------------------------------------+-------------------+-------------------------+
| NAME       | STATE   | STATE_CODE                          | STATE_MESSAGE     | DATA_TIMESTAMP          |
+------------+---------+-------------------------------------+-------------------+-------------------------+
| DT_ORDERS  | SKIPPED | NOT_EFFECTIVE_TICK_TO_REFRESH       | ...               | 2025-01-16 11:50:00.000 |
| DT_ORDERS  | SKIPPED | UPSTREAM_FAILED                     | ...               | 2025-01-16 11:40:00.000 |
+------------+---------+-------------------------------------+-------------------+-------------------------+
  • <C>state_code</C>를 해석하세요:
상태 코드 의미 해결책
UPSTREAM_FAILED 상위 다이나믹 테이블이 실패하거나 건너뛰어졌습니다 먼저 상위 테이블을 고치세요
NOT_EFFECTIVE_TICK_TO_REFRESH Snowflake가 이 예약 리프레시 시도가 효과적이지 않다고 판단했습니다(리프레시 지속 시간이 target lag를 크게 초과) 웨어하우스 크기를 늘리거나, 정의를 최적화하거나, target lag를 늘리세요

<C>UPSTREAM_FAILED</C>를 가진 SKIPPED는 상위 테이블이 이 주기에 실패해서 단일 리프레시 시도가 건너뛰어졌음을 의미합니다. SUSPENDED는 반복 실패(기본적으로 연속 5회 실패) 후 테이블이 완전히 리프레시를 멈췄음을 의미합니다.

이전 리프레시가 아직 실행 중일 때 다음 예약 리프레시 시도가 도착하면, 새 예약 리프레시 시도는 건너뛰어지고 현재 리프레시가 완료되도록 허용됩니다. 겹치는 리프레시로 인한 건너뜀을 줄이려면 웨어하우스 크기를 늘리거나 target lag를 늘리세요.

  • NOT_EFFECTIVE_TICK_TO_REFRESH로 연속 건너뜀이 많다면, 리프레시가 target lag보다 훨씬 오래 걸리기 때문에 Snowflake가 조정하고 있는 거예요. 예를 들어 target lag가 1분인데 리프레시 지속 시간이 1시간이면 대부분의 예약 리프레시 시도가 건너뛰어집니다. 해결하려면 target lag를 현실적인 값으로 늘리거나 리프레시 성능을 개선하세요. 증분 리프레시 쿼리 최적화를 참고하세요.

참고 수동 리프레시(<C>ALTER DYNAMIC TABLE ... REFRESH</C>)는 절대 건너뛰지 않지만, 다운스트림 소비자가 있는 다이나믹 테이블을 자주 수동 리프레시하면 그 다운스트림 다이나믹 테이블이 예약대로 리프레시되지 못하게 막을 수 있어요.

리프레시는 비용을 보이지만 새 행을 만들지 않음

Snowflake가 상위 변경을 감지하고 웨어하우스를 재개해 평가하면, 0행 리프레시도 여전히 컴퓨트를 소비합니다.

  • 최근 리프레시가 웨어하우스 리소스를 소비했는지 확인하세요:
SELECT name, state,
       statistics:numInsertedRows::INT AS rows_inserted,
       statistics:numDeletedRows::INT AS rows_deleted,
       DATEDIFF('second', refresh_start_time, refresh_end_time) AS duration_sec
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(NAME_PREFIX => 'mydb.myschema.dt_orders'))
ORDER BY refresh_start_time DESC
LIMIT 10;
+------------+-----------+---------------+--------------+--------------+
| NAME       | STATE     | ROWS_INSERTED | ROWS_DELETED | DURATION_SEC |
+------------+-----------+---------------+--------------+--------------+
| DT_ORDERS  | NO_DATA   | NULL          | NULL         | 0            |
| DT_ORDERS  | SUCCEEDED | 0             | 0            | 3            |
| DT_ORDERS  | SUCCEEDED | 0             | 0            | 2            |
| DT_ORDERS  | SUCCEEDED | 15            | 2            | 5            |
+------------+-----------+---------------+--------------+--------------+
  • 두 유형의 0행 리프레시를 이해하세요:
유형 웨어하우스 사용 비용 설명
NO_DATA 아니요 없음 상위 객체에서 변경이 감지되지 않았습니다. 웨어하우스는 일시 중단 상태를 유지합니다.
0행 SUCCEEDED 예 컴퓨트 크레딧 소비 상위에서 변경이 감지되어 웨어하우스가 재개해 평가했지만, 다이나믹 테이블에 적용된 순 결과는 0행이었습니다.
  • 0행 리프레시가 자주 발생하고 비용이 걱정된다면, 상위 프로세스가 다이나믹 테이블의 출력에 영향을 주지 않는 변경을 생성하는지(예: 정의에서 참조하지 않는 컬럼 업데이트) 확인하세요.

자세한 내용은 다이나믹 테이블 비용 이해하기를 참고하세요.

다음 단계

SELECT timestamp,
       resource_attributes:"snow.executable.name"::VARCHAR AS dt_name,
       resource_attributes:"snow.query.id"::VARCHAR AS query_id,
       value:message::VARCHAR AS error
FROM my_event_table
WHERE resource_attributes:"snow.executable.type" = 'DYNAMIC_TABLE'
AND resource_attributes:"snow.database.name" = 'MY_DB'
AND value:state = 'FAILED'
ORDER BY timestamp DESC;
+-------------------------+-------------------+--------------+----------------------------------------------+
| TIMESTAMP               | DT_NAME           | QUERY_ID     | ERROR                                        |
+-------------------------+-------------------+--------------+----------------------------------------------+
| 2025-01-16 12:00:00.000 | DT_ORDERS         | 01b7e3f2-... | SQL compilation error: invalid identifier ... |
+-------------------------+-------------------+--------------+----------------------------------------------+

다이나믹 테이블 모니터링을 위한 이벤트 테이블 설정에 대한 자세한 내용은 다이나믹 테이블 모니터링을 참고하세요.

  • 여기서 다루지 않은 문제를 만나면 Snowflake Support에 문의하세요.

더 알아보기 (Learn more)