Classic 아키텍처와 함께하는 Snowpipe Streaming 모범 사례

Classic 아키텍처와 함께하는 Snowpipe Streaming 모범 사례

Snowpipe Streaming classic을 가장 효율적으로 사용하기 위한 비용 최적화, 성능, 지연 시간, exactly-once 전달 모범 사례를 알려드릴게요. 이 지침을 따르면 크레딧을 아끼고 지연 시간을 낮게 유지할 수 있습니다.

출처: Snowflake 문서

본문

비용 최적화

모범 사례로, 초당 더 많은 데이터를 쓰는 더 적은 수의 Snowpipe Streaming 클라이언트로 API를 호출하는 것을 권장합니다. Java나 Scala 애플리케이션을 사용해 IoT 장치나 센서 같은 여러 소스의 데이터를 집계한 다음, Snowflake Ingest SDK를 사용해 API를 호출해 더 높은 흐름 속도로 데이터를 로드하세요. API는 계정의 여러 대상 테이블에 걸쳐 데이터를 효율적으로 집계합니다.

단일 Snowpipe Streaming 클라이언트는 데이터를 보내기 위해 여러 채널을 열 수 있지만, 클라이언트 비용은 활성 클라이언트당으로만 청구됩니다. 채널 수는 클라이언트 비용에 영향을 주지 않아요. 따라서 성능과 비용 최적화를 위해 클라이언트당 여러 채널을 사용하는 것을 권장합니다.

일괄(batch) 수입과 스트리밍 수입 양쪽에 같은 테이블을 사용하면, 선점된 파일 마이그레이션 작업 덕분에 Snowpipe Streaming 컴퓨트 비용도 줄일 수 있어요.

Snowpipe Streaming은 Snowpipe Streaming이 데이터를 삽입하는 자동 클러스터링(Automatic Clustering)이 활성화된 테이블의 모든 파일 마이그레이션 컴퓨트 비용을 처리하고 청구합니다. 이 프로세스는 같은 트랜잭션 안에서 데이터를 최적화·마이그레이션하며, 이전에 자동 클러스터링과 관련된 비용을 통합합니다.

성능 권장 사항

고처리량 배포에서 최적의 성능을 위해 다음 조치를 권장합니다.

  • 여러 행을 로드한다면 insertRows를 사용하는 것이 insertRow를 여러 번 호출하는 것보다 더 효율적이고 비용 효과적입니다. 락에 쓰는 시간이 줄기 때문이에요.
  • insertRows에 전달하는 각 행 일괄 처리의 크기를 압축 기준 16 MB 미만으로 유지하세요. 행 일괄 처리의 최적 크기는 10~16 MB입니다.
  • TIME, DATE, 모든 TIMESTAMP 컬럼의 값은 java.time 패키지의 지원 타입 중 하나로 전달하세요.
  • OpenChannelRequest.builder로 채널을 만들 때 OnErrorOption을 OnErrorOption.CONTINUE로 설정하고, insertRows의 반환 값을 수동으로 확인해 잠재적 수입 오류를 점검하세요. 이 접근 방식은 현재 OnErrorOption.ABORT를 사용할 때 던져지는 예외에 의존하는 것보다 더 나은 성능을 낸답니다.
  • 기본 로그 레벨을 DEBUG로 설정할 때는 다음 로거들이 INFO로 계속 로깅하게 하세요. 이들의 DEBUG 출력은 매우 장황해서 상당한 성능 저하를 일으킬 수 있어요.
    • net.snowflake.ingest.internal.apache.parquet
    • org.apache.parquet
  • 채널은 클라이언트가 활발히 데이터를 삽입할 때 오래 살아 있어야 하며, offset token 정보가 보존되므로 재사용해야 합니다. 데이터 삽입 후 채널을 닫지 마세요. 채널 안의 데이터는 MAX_CLIENT_LAG에 구성된 시간에 따라 자동으로 플러시되기 때문이에요.

지연 시간 권장 사항

Snowpipe Streaming을 사용할 때 지연 시간은 채널에 쓰인 데이터가 Snowflake에서 쿼리 가능해질 때까지의 속도를 의미합니다. Snowpipe Streaming은 채널 안의 데이터를 매 1초마다 자동으로 플러시하므로, 데이터가 플러시되도록 채널을 명시적으로 닫을 필요가 없어요.

MAX_CLIENT_LAG로 지연 시간 구성하기

Snowflake Ingest SDK 버전 2.0.4 이상에서는 MAX_CLIENT_LAG 옵션으로 데이터 플러시 지연 시간을 미세 조정할 수 있습니다.

  • 표준 Snowflake 테이블(비-Iceberg): 기본 MAX_CLIENT_LAG은 1초입니다. 원하는 플러시 지연 시간을 1초부터 최대 10분 사이 어디든 설정하도록 이를 덮어쓸 수 있어요.
  • Snowflake 관리 Iceberg 테이블: Snowflake Ingest SDK 버전 3.0.0 이상에서 지원되며, 기본 MAX_CLIENT_LAG은 30초입니다. 이 기본값은 쿼리 성능에 유리한 최적화된 Parquet 파일이 생성되도록 돕습니다. 더 낮은 값을 설정할 수 있지만, 예외적으로 높은 처리량이 아니라면 일반적으로 권장하지 않아요.

최적 성능을 위한 지연 시간 권장 사항

MAX_CLIENT_LAG을 효과적으로 설정하면 쿼리 성능과 내부 마이그레이션 프로세스(Snowflake가 작은 파티션을 컴팩션하는 과정)에 상당한 영향을 줄 수 있어요.

저처리량 시나리오, 즉 매초 소량의 데이터(예: 1행 또는 1 KB)만 보내는 경우에는 잦은 플러시가 많은 작은 파티션을 만들 수 있습니다. 이는 특히 마이그레이션 프로세스가 컴팩션하기 전에 쿼리가 실행되면 Snowflake가 아주 많은 작은 파티션을 해석해야 하므로 쿼리 컴파일 시간을 늘릴 수 있어요.

따라서 MAX_CLIENT_LAG을 target 지연 시간 요구사항이 허용하는 한 높게 설정해야 합니다. 삽입된 행을 더 오래 버퍼링하면 Snowpipe Streaming이 더 잘 크기 조정된 파티션을 만들 수 있고, 쿼리 성능이 개선되며 마이그레이션 오버헤드가 줄어듭니다.

예를 들어 스트리밍 데이터를 병합하거나 변환하는 작업이 매분 실행된다면, 최적의 MAX_CLIENT_LAG은 50~55초 사이일 수 있어요. 그러면 다운스트림 프로세스가 실행되기 직전에 데이터가 더 큰 덩어리로 플러시됩니다.

Snowpipe Streaming용 Kafka 커넥터

Snowpipe Streaming용 Kafka 커넥터에는 자체 내부 버퍼가 있다는 점에 주의하세요. Kafka 버퍼 플러시 시간에 도달하면 데이터는 Snowpipe Streaming을 통해 표준 1초 지연 시간으로 Snowflake에 전송됩니다. 자세한 내용은 buffer.flush.time 설정을 참고하세요.

Exactly-once 전달 모범 사례

Exactly-once 전달을 달성하는 것은 어려울 수 있으며, 커스텀 코드에서 다음 원칙을 지키는 것이 매우 중요합니다.

  • 예외, 실패, 크래시에서 적절히 복구하려면 항상 채널을 다시 열고 최신 커밋된 offset token으로 수입을 재시작해야 합니다.
  • 애플리케이션이 자체 offset을 유지하더라도, Snowflake가 제공하는 최신 커밋된 offset token을 소스 오브 트루스로 사용하고 그에 따라 자체 offset을 리셋하는 것이 중요합니다.
  • 자체 offset을 소스 오브 트루스로 취급해야 하는 유일한 경우는 Snowflake의 offset token이 NULL로 설정되거나 리셋된 때입니다. NULL offset token은 보통 다음 중 하나를 의미합니다:
    • 새 채널이라 offset token이 설정되지 않았습니다.
    • 대상 테이블이 삭제·재생성되어 채널이 새 것으로 간주됩니다.
    • 채널을 통한 수입 활동이 30일 동안 없어 채널이 자동으로 정리되고 offset token 정보가 유실되었습니다.
  • 필요하면 최신 커밋된 offset token을 기준으로 이미 커밋된 소스 데이터를 주기적으로 정리하고 자체 offset을 전진시킬 수 있어요.
  • Snowpipe Streaming 채널이 활성 상태일 때 테이블 스키마가 수정되면 채널을 다시 열어야 합니다. Snowflake Kafka 커넥터는 이 시나리오를 자동으로 처리하지만, Snowflake Ingest SDK를 직접 사용한다면 채널을 직접 다시 열어야 해요.

Snowpipe Streaming과 함께하는 Kafka 커넥터가 exactly-once 전달을 달성하는 방식에 대한 자세한 내용은 Exactly-once 의미론을 참고하세요.

더 알아보기 (Learn more)