증분 새로 고침을 위한 쿼리 최적화

새 동적 테이블 쿼리를 설계하거나 증분 새로 고침을 위해 기존 쿼리를 최적화하려는 경우 이 페이지를 사용합니다. 이 가이드에서는 성능이 우수한 연산자, 신중하게 처리해야 하는 연산자, 성능 향상을 위해 쿼리를 재구성하는 방법을 보여줍니다.

증분 새로 고침에 지원되는 쿼리 구문의 전체 목록은 동적 테이블에 대해 지원되는 쿼리 섹션을 참조하세요.

연산자별 성능 기대치

동적 테이블 쿼리를 최적화하기 전에 증분 새로 고침의 이점을 누리는 연산자 및 문제를 일으킬 수 있는 연산자를 이해해야 합니다.

참고

짧은 쿼리(10초 미만)는 쿼리 최적화 및 웨어하우스 예약과 같은 고정 오버헤드로 인해 성능 향상이 더 적을 수 있습니다.

일관되게 우수한 성능을 발휘하는 연산자

이러한 연산자는 증분 새로 고침에서 효율적으로 작동합니다.

  • SELECT

  • WHERE

  • FROM <base table>

  • UNION ALL

  • QUALIFY [ RANK | ROW_NUMBER | DENSE_RANK ] … = 1

Snowflake가 각 연산자를 처리하는 방법에 대한 자세한 내용은 :ref:`연산자 참조 테이블 <label-dt-incremental-operators-reference>`을 참조하세요.

데이터 지역성의 영향을 받는 연산자

이러한 연산자의 경우 성능은 :ref:`데이터 지역성 <label-dt-optimize-locality>`에 따라 달라지며, 이는 데이터를 구성하는 방법 및 키를 기준으로 변경이 발생하는 위치입니다.

  • INNER JOIN

  • OUTER JOIN

  • GROUP BY

  • DISTINCT

  • ``OVER``(윈도우 함수)

변경 사항이 그룹화 또는 파티션 키의 작은 부분에만 영향을 미치는 경우 이러한 연산자는 우수한 성능을 발휘합니다. 데이터 지역성이 좋지 않거나 변경 사항이 여러 키에 분산되어 있으면 증분 새로 고침이 전체 새로 고침보다 느릴 수 있습니다.

Snowflake가 각 연산자를 처리하는 방법에 대한 자세한 내용은 :ref:`연산자 참조 테이블 <label-dt-incremental-operators-reference>`을 참조하세요.

일반적인 최적화 패턴

다음 섹션에서는 지역성을 구분하는 연산자를 사용하는 쿼리를 최적화하는 일반적인 패턴을 보여줍니다.

집계 최적화

:doc:`GROUP BY </sql-reference/constructs/group-by>`를 사용할 때, Snowflake는 변경 사항이 포함된 모든 그룹화 키에 대한 집계를 다시 계산합니다. 성능은 다음 요소에 따라 달라집니다.

  • 데이터 클러스터링: 그룹화 키로 클러스터링된 소스 데이터가 최상의 성능을 발휘합니다.

  • 배포 변경: 그룹화 키의 5% 미만에 영향을 미치는 변경을 목표로 합니다.

  • 주요 복잡성: 단순 열 참조는 복합 식보다 성능이 우수합니다.

문제: 그룹화 키의 복합 식

이 쿼리는 그룹화 키가 식이므로 성능이 저하됩니다.

CREATE DYNAMIC TABLE hourly_sums
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT DATE_TRUNC('minute', ts), SUM(amount)
  FROM transactions
  GROUP BY 1;
Copy

해결책: 식 구체화

두 개의 동적 테이블로 분할하여 간단한 그룹화 키를 노출합니다.

CREATE DYNAMIC TABLE transactions_with_minute
  TARGET_LAG = DOWNSTREAM
  WAREHOUSE = my_warehouse
AS
  SELECT DATE_TRUNC('minute', ts) AS ts_minute, amount
  FROM transactions;

CREATE DYNAMIC TABLE hourly_sums
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT ts_minute, SUM(amount)
  FROM transactions_with_minute
  GROUP BY 1;
Copy

이제 ``GROUP BY``는 단순 열에서 작동하며 중간 테이블은 더 나은 :ref:`데이터 지역성 <label-dt-optimize-locality>`의 이점을 얻습니다.

조인 최적화

조인 성능은 어느 쪽을 변경하는지 그리고 데이터를 어떻게 클러스터링하는지에 따라 다릅니다.

INNER JOIN: Snowflake는 왼쪽의 변경 사항을 오른쪽 테이블과 조인한 다음, 오른쪽의 변경 사항을 왼쪽 테이블과 조인합니다. 조인은 한 쪽이 작거나 자주 변경되지 않을 때 잘 수행됩니다.

OUTER JOIN: Snowflake는 일치하지 않는 행에 대한 NULL 값도 계산해야 합니다. 어느 쪽이 변경되느냐에 따라 성능에 상당한 영향을 미칩니다.

문제: 클러스터링이 불량한 양쪽의 큰 테이블

두 소스 테이블 모두 조인 키로 클러스터링되지 않습니다:

CREATE DYNAMIC TABLE order_details
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT o.order_id, o.customer_id, p.product_name, o.quantity
  FROM orders o
  JOIN products p ON o.product_id = p.product_id;
Copy

해결책: 덜 자주 변경되는 테이블 클러스터링

조인 키로 차원 테이블을 클러스터링합니다. 그러면 조인이 더 나은 지역성의 이점을 누릴 수 있습니다.

ALTER TABLE products CLUSTER BY (product_id);

CREATE DYNAMIC TABLE order_details
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT o.order_id, o.customer_id, p.product_name, o.quantity
  FROM orders o
  JOIN products p ON o.product_id = p.product_id;
Copy

OUTER JOINs의 경우:

  • 더 자주 변경되는 테이블을 LEFT에 배치합니다.

  • OUTER 키워드 반대쪽의 변경을 최소화합니다.

  • FULL OUTER JOINs의 경우, 우수한 지역성은 양쪽 모두에서 매우 중요합니다.

윈도우 함수 최적화

Snowflake는 변경 사항이 포함된 모든 파티션 키에 대해 :doc:`윈도우 함수 </sql-reference/functions-window>`를 다시 계산합니다. ``GROUP BY``와 유사하게 최적화합니다.

주요 요구 사항:

  • PARTITION BY 절을 항상 포함합니다. PARTITION BY 절이 없는 윈도우 함수는 전체 다시 계산을 수행합니다.

  • 파티션 키로 소스 데이터를 클러스터링합니다.

  • 파티션의 5% 미만에 대한 변경 사항을 유지합니다.

문제: 파티션 클러스터링이 없는 윈도우 함수

소스 테이블은 파티션 키로 클러스터링되지 않습니다.

CREATE DYNAMIC TABLE ranked_sales
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT
    region,
    salesperson,
    amount,
    RANK() OVER (PARTITION BY region ORDER BY amount DESC) as sales_rank
  FROM daily_sales;
Copy

해결책: 파티션 키로 클러스터링

윈도우 함수가 지역성의 이점을 누릴 수 있도록 파티션 키로 소스 테이블을 클러스터링합니다.

ALTER TABLE daily_sales CLUSTER BY (region);

CREATE DYNAMIC TABLE ranked_sales
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT
    region,
    salesperson,
    amount,
    RANK() OVER (PARTITION BY region ORDER BY amount DESC) as sales_rank
  FROM daily_sales;
Copy

효율적으로 중복 제거(DISTINCT 및 QUALIFY)

DISTINCTQUALIFY 모두 중복을 제거할 수 있지만, 성능은 다릅니다.

DISTINCT: ``GROUP BY ALL``과 동등합니다. 지역성은 성능에 직접적인 영향을 미칩니다. 지역성이 좋지 않으면 새로 고침이 느려집니다.

ROW_NUMBER = 1인 QUALIFY: Snowflake는 동적 테이블의 최상위 프로젝션에 있는 경우 QUALIFY ROW_NUMBER() ... = 1 패턴을 최적화합니다. 이 패턴은 전체 새로 고침보다 일관되게 더 빠르게 수행됩니다.

최적화는 OVER() 절의 모든 PARTITION BY 및 ORDER BY 키가 동적 테이블(최상위 수준 프로젝션에 포함됨)에 유지될 때 가장 잘 작동합니다.

권장 사항: 가능한 경우 DISTINCT 대신 QUALIFY 사용

다음 예에서는 DISTINCT 를 사용합니다.

CREATE DYNAMIC TABLE unique_customers
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT DISTINCT customer_id, customer_name, email
  FROM customer_events;
Copy

다음 예에서는 QUALIFY 를 사용합니다.

CREATE DYNAMIC TABLE unique_customers
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT customer_id, customer_name, email, event_time
  FROM customer_events
  QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY event_time DESC) = 1;
Copy

QUALIFY 버전은 유지할 복제본(가장 최근 버전)을 더 명확히 설명하며 일관되게 성능이 우수합니다.

중복 DISTINCT 작업 제거

각 DISTINCT는 새로 고칠 때마다 리소스를 사용합니다. 데이터가 이미 고유하거나 업스트림에서 중복을 제거하는 경우 불필요한 DISTINCT 절을 제거합니다.

연산자 참조

다음 테이블은 Snowflake가 증분 새로 고침 중 각 SQL 연산자를 처리하는 방법을 설명합니다.

연산자

Snowflake가 처리하는 방법

성능 참고

SELECT

변경된 행에만 식을 적용합니다.

성능이 우수합니다. 특별한 고려 사항이 없습니다.

WHERE

변경된 행에 대해서만 조건자를 평가합니다.

성능이 우수합니다. 비용은 변경 사항에 따라 선형적으로 증가합니다. 참고: 매우 선택적인 WHERE는 출력이 변경되지 않더라도 웨어하우스 가동 시간이 필요할 수 있습니다.

FROM <table>

마지막 새로 고침 이후 Snowflake가 추가하거나 제거한 마이크로 파티션을 스캔합니다.

비용은 변경된 파티션의 볼륨에 따라 증가합니다. 변경 사항을 소스 테이블의 약 5%로 제한합니다.

UNION ALL

양쪽에서 변경 사항의 합집합을 가져옵니다.

성능이 우수합니다. 특별한 고려 사항이 없습니다.

WITH (CTEs)

각 공통 테이블 식의 변경 사항을 계산합니다.

성능은 우수하지만, 지나치게 복잡한 단일 테이블 정의는 피하세요. 여러 동적 테이블로 분할하는 것이 좋습니다.

스칼라 집계

입력이 변경되면 집계를 완전히 다시 계산합니다.

성능이 중요한 테이블에서는 피하세요. 대신 상수로 그룹화하는 것이 좋습니다.

GROUP BY

변경된 그룹화 키에 대한 집계를 다시 계산합니다.

키를 그룹화하여 소스를 클러스터링합니다. 키에 복합 식을 사용하지 마세요. 집계 최적화 섹션을 참조하십시오.

DISTINCT

GROUP BY ALL과 동등합니다.

지역성을 구분합니다. 대신 QUALIFY를 사용하는 것이 좋습니다. 효율적으로 중복 제거(DISTINCT 및 QUALIFY) 섹션을 참조하십시오.

윈도우 함수

변경된 파티션 키를 다시 계산합니다.

PARTITION BY를 항상 포함합니다. 파티션 키로 소스를 클러스터링합니다. 윈도우 함수 최적화 섹션을 참조하십시오.

INNER JOIN

양쪽의 변경 사항을 다른 테이블과 조인합니다.

한 쪽이 작을 때 성능이 우수합니다. 덜 자주 변경되는 쪽을 클러스터링합니다. 조인 최적화 섹션을 참조하십시오.

OUTER JOIN

NULL 계산을 위해 내부 조인과 NOT EXISTS 쿼리를 결합합니다.

가장 지역성에 민감한 연산자입니다. 조인 최적화 섹션을 참조하십시오.

LATERAL FLATTEN

변경된 행에만 평면화를 적용합니다.

성능이 우수합니다. 비용은 변경 사항에 따라 선형적으로 증가합니다.

순위가 있는 QUALIFY

ROW_NUMBER/RANK/DENSE_RANK … = 1에 최적화된 경로를 사용합니다.

매우 효율적입니다. 동적 테이블의 최상위 프로젝션에 QUALIFY를 배치합니다.