Snowflake 비용 효율화

문주은·2024년 1월 12일

Snowflake 비용 효율화 가이드

Snowflake는 사용한 만큼만 비용이 청구되는 구조이기 때문에, 비용이 어디서, 왜 발생하는지 이해하는 것이 최적화의 출발점입니다. 이 글에서는 Snowflake의 비용 구성 요소부터 실무에서 바로 활용할 수 있는 모니터링·최적화 쿼리까지 정리했습니다.


1. Snowflake 비용 구성 요소

Snowflake 비용은 크게 컴퓨팅, 스토리지, 데이터 전송 세 가지로 나뉩니다.

1-1. Computing Resource

컴퓨팅 리소스를 사용하는 경우는 다음과 같습니다.

  • Virtual Warehouse
    • 데이터 로딩, 쿼리 실행, DML 작업에 사용
    • 워크로드에 맞춰 유연하게 확장 가능
    • 초당 과금이므로 실제로 소비한 크레딧에 대해서만 비용이 발생
  • Cloud Services
    • 인증, 메타데이터 관리, 액세스 제어 같은 백그라운드 작업에 크레딧 사용
    • 일일 사용량이 Warehouse 비용의 10%를 초과한 경우에만 요금이 청구되므로 실제 청구로 이어지는 경우는 드뭄
  • Serverless
    • Virtual Warehouse가 아닌 Snowflake 관리형 컴퓨팅 리소스를 사용하는 유형
    • 자동 클러스터링, Materialized View, Search Optimization, Snowpipe, 복제 등의 기능에 사용

1-2. Storage

  • 데이터 로딩·언로딩을 위해 스테이지에 올린 파일 비용
  • 테이블 데이터 등 데이터베이스 저장 비용 포함
  • 테이블 데이터는 높은 압축률로 저장되므로 전체 비용에서 차지하는 비율은 낮은 편

1-3. Data Transfer & Egress

  • 수신: 외부 → Snowflake, 송신: Snowflake → 외부
  • 동일 region 내 데이터 전송은 무료
  • 같은 클라우드 플랫폼이라도 다른 region으로 데이터를 전송하면 바이트당 요금이 청구됨

2. 비용 관리 프레임워크

비용 관리 프레임워크는 가시화 → 통제 → 최적화 흐름으로 Snowflake 비용을 체계적으로 관리하는 방법입니다.

2-1. Visibility (가시화)

비용의 패턴을 파악하고, 누가 어떤 목적으로 비용을 발생시켰는지 확인하는 단계입니다.

Snowflake Dashboard > Admin > Cost Management 에서 확인할 수 있습니다.

2-2. Control (모니터링)

예산 한도와 가드레일을 설정하고 모니터링하는 단계입니다.

Resource Monitor 구성

  • 사용자 관리 Virtual Warehouse 및 Cloud Services 계층별 크레딧 사용량 모니터링
  • 월별 한도 및 사용자 지정 한도 설정 가능
  • 지정한 임계값에 도달하면 이메일 알림 또는 Warehouse 일시 중지 기능 제공

Auto-Suspend & Auto-Resume 설정 가이드

  • Snowflake는 모든 쿼리 결과를 캐싱합니다.
  • 반복적인 쿼리 워크로드의 경우, 캐시를 활용하면 성능상 큰 이점이 있습니다.
  • BI 및 SELECT 쿼리 위주의 경우, Auto-Suspend를 10분 이내로 설정 권장
  • DevOps / DataOps / DataScience 워크로드의 경우, 약 5분 이내로 설정 권장

Auto-Suspend & Auto-Resume duration 가이드

Auto-Suspend & Auto-Resume 점검 쿼리

-- Warehouse 목록 조회
SHOW WAREHOUSES;
-- Resource Monitor를 사용하지 않는 Warehouse 조회
SHOW WAREHOUSES;
SELECT "name" AS WAREHOUSE_NAME, "size" AS WAREHOUSE_SIZE
  FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
 WHERE "resource_monitor" = 'null';
-- Auto-Suspend(자동 중단)가 1시간 이상인 Warehouse 조회
SHOW WAREHOUSES;
SELECT "name" AS WAREHOUSE_NAME, "size" AS WAREHOUSE_SIZE
  FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
 WHERE "auto_suspend" >= 3600;  -- 3600초 = 1시간
-- Auto-Resume가 False인 Warehouse 조회
SHOW WAREHOUSES;
SELECT "name" AS WAREHOUSE_NAME, "size" AS WAREHOUSE_SIZE
  FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
 WHERE "auto_resume" = 'false';

2-3. Optimization (최적화)

적절한 Warehouse 타입 선택크기 조정을 통해 비용을 최적화하는 단계입니다.

  • Virtual Warehouse 타입: Standard(일반형), Snowpark-optimized Warehouse(대용량 메모리형) 두 가지
  • 작업 실행 시 중간 결과값은 Warehouse 메모리에 저장되며, 다음 순서로 spill(넘침) 이 발생합니다.

메모리 부족 → Warehouse의 Local Disk로 spill → Local Disk 부족 → Remote Storage로 spill

⚠️ spill이 발생할수록 데이터를 얻기까지의 시간과 비용이 증가합니다.

최근 45일간 Disk Spill 발생 Top-10 쿼리

USE WAREHOUSE compute_s;

SELECT query_id,
       SUBSTR(query_text, 1, 50) AS partial_query_text,
       user_name, warehouse_name, warehouse_size,
       bytes_spilled_to_remote_storage,
       start_time, end_time,
       total_elapsed_time / 1000 AS elapsed_sec,
       total_elapsed_time
  FROM snowflake.account_usage.query_history
 WHERE bytes_spilled_to_remote_storage > 0
   AND start_time::date > DATEADD('days', -45, CURRENT_DATE)
 ORDER BY bytes_spilled_to_remote_storage DESC
 LIMIT 10;

결과가 있다면 해당 query_id로 쿼리를 추적한 뒤, 최적화 필요 여부를 판단합니다.

최근 45일간 Warehouse 캐시 스캔 비율

SELECT WAREHOUSE_NAME,
       COUNT(*) AS QUERY_COUNT,
       SUM(BYTES_SCANNED) AS BYTES_SCANNED,
       SUM(BYTES_SCANNED * PERCENTAGE_SCANNED_FROM_CACHE) AS BYTES_SCANNED_FROM_CACHE,
       SUM(BYTES_SCANNED * PERCENTAGE_SCANNED_FROM_CACHE) / SUM(BYTES_SCANNED) AS PERCENT_SCANNED_FROM_CACHE
  FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
 WHERE START_TIME >= DATEADD('DAYS', -45, CURRENT_TIMESTAMP())
   AND BYTES_SCANNED > 0
 GROUP BY 1
 ORDER BY 5;

PERCENT_SCANNED_FROM_CACHE 비율이 낮다면, 캐시를 활용할 수 있도록 쿼리 튜닝을 고려합니다.

최근 45일간 Warehouse 부하 확인

SELECT TO_DATE(START_TIME) AS DATE,
       WAREHOUSE_NAME,
       SUM(AVG_RUNNING) AS SUM_RUNNING,
       SUM(AVG_QUEUED_LOAD) AS SUM_QUEUED
  FROM SNOWFLAKE.ACCOUNT_USAGE.WAREHOUSE_LOAD_HISTORY
 WHERE TO_DATE(START_TIME) >= DATEADD('DAYS', -45, CURRENT_TIMESTAMP())
 GROUP BY 1, 2
HAVING SUM(AVG_QUEUED_LOAD) > 0;
  • Warehouse 부하는 쿼리 실행 시 queue에 얼마나 작업이 쌓였는지로 확인할 수 있습니다.
  • SUM_QUEUED >= 1 이면 Warehouse 크기 확장을 고려합니다.

최근 한 달간 Full Table Scan을 가장 많이 한 사용자

SELECT USER_NAME,
       COUNT(*) AS COUNT_OF_QUERIES
  FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
 WHERE START_TIME >= DATEADD(month, -1, CURRENT_TIMESTAMP())
   AND PARTITIONS_SCANNED > (PARTITIONS_TOTAL * 0.95)
   AND QUERY_TYPE NOT LIKE 'CREATE%'
 GROUP BY 1
 ORDER BY 2 DESC;

2-4. Warehouse 사이즈 조절 기준

Warehouse 사이즈 조절 기준


3. 그 외 확인해야 할 포인트

  • dbt CLI의 drop + create 동작 주의
    • dbt CLI로 테이블을 dropcreate 하면 __DBT_BACKUP 접미사가 붙은 백업 테이블이 생성됩니다.
    • 이는 더 이상 참조되지 않는 고아(orphan) 테이블이므로, 불필요한 스토리지 비용을 막기 위해 주기적으로 삭제해야 합니다.

용어 정리

용어설명
ObjectSnowflake의 관리 대상 (Database, Warehouse 등)
Auto-Suspend일정 시간 미사용 시 Warehouse 자동 중단
Auto-Resume쿼리 요청 시 중단된 Warehouse 자동 재개
profile
Data Engineer

0개의 댓글