현재 우리는 데이터 시대에 살고 있습니다. 분석해야 하는 데이터양이 증가함에 따라 데이터 처리는 분산 컴퓨팅 아키텍처(Shared-Nothing)를 통해 처리되고 있습니다. 또 하나 주목해야 하는 점은 분산 처리 시스템이 기존 데이터 센터에서 퍼블릭 클라우드로 전환되고 있는 추세입니다. 퍼블릭 클라우드는 거의 무제한의 컴퓨팅 및 스토리지 리소스를 온디맨드 방식으로 제공하고 있으며, SaaS 모델은 기업용 솔루션을 비용과 복잡성으로 인해 이전에 도입하여 사용할 수 없었던 사용자들에게도 엔터프라이즈 수준의 솔루션을 제공하고 사용할 수 있습니다. 이와 같은 환경적인 변화에 따라 기존 데이터 플랫폼 제공 업체들은 새로운 환경에 적응하기 위해 다양한 시도를 하고 있지만, 동시에 퍼블릭 클라우드 환경에 완벽하게 적응하는 데 어려움을 겪고 있습니다. 첫 번째 어려움은 기존 솔루션은 고정 리소스용으로 설계되었기 때문에 클라우드의 탄력성을 완벽하게 지원하지 않고 있습니다. 두 번째로는 복잡한 ETL 파이프라인 및 물리적 튜닝 방식에 대한 의존도 때문에 기존 솔루션은 새로운 유형의 반정형 데이터를 빠르게 처리하고 진화되는 워크로드 유연성 및 다양성을 충족할 수 없습니다.
Snowflake는 클라우드 환경에서 효율적인 데이터 분석을 위해 새로운 분석 플랫폼이 필요하다고 판단했습니다. Snowflake 미션은 클라우드를 위한 엔터프라이즈 수준의 클라우드 데이터 플랫폼을 구축하는 것이었습니다. 즉, Snowflake는 멀티-테넌트, 트랜잭션, 보안, 고도로 확장 가능하고 탄력적인 시스템으로 표준 SQL 지원뿐만 아니라 반정형 데이터 및 스키마-리스 데이터 지원 기능들이 내장되어 있습니다. 사용자는 데이터를 클라우드에 업로드하고 친숙한 SQL 도구와 인터페이스를 사용하여 바로 쿼리할 수 있습니다. 사용자는 Snowflake를 AWS와 같은 퍼블릭 클라우드 환경에서 사용한 만큼만 비용을 지불하는 서비스로 제공받을 수 있게 되었습니다. Snowflake는 2012년 말에 구현하기 시작했으며, 2015년 6월부터 사용자들에게 공급하고 있습니다. 오늘날 Snowflake는 점점 더 많은 고객사의 운영 환경에 도입되어, 매일 수 PB 데이터에 대해 수백만 개의 쿼리가 실행되고 있습니다.
소개
클라우드 시대는 데이터 센터와 로컬 PC에 설치되어 실행되는 소프트웨어에서 벗어나 AWS, GCP 또는 Azure와 같은 퍼블릭 클라우드 플랫폼 제공업체가 호스팅하는 공유 데이터 센터와 SaaS 솔루션으로의 전환을 의미하고 있습니다. 클라우드의 공유 인프라는 확장성 및 가용성, 예측할 수 없는 사용 요구에 적응하는 종량제 비용 모델로 그 특징을 정의할 수 있습니다. 그러나 이러한 이점은 소프트웨어가 클라우드 기능을 완벽하게 지원하는 경우에만 클라우드 환경에서 제공하는 다양한 혜택을 얻을 수 있음을 의미합니다. 기존 EDW 솔루션은 클라우드 시대 이전에 설계/개발되었습니다. 즉, 온-프레미스 정적 실행 환경에서만 작동되도록 설계되어 클라우드 환경에 실행되기에는 아키텍처에 관련된 다양한 제약사항들이 존재했습니다. 더욱이, 오늘날 기업 환경에서는 플랫폼만 변경된 것이 아니라, 데이터도 변경되었습니다. 기존 EDW내의 데이터는 트랜잭션 시스템, ERP, CRM 등 기업 내에 존재하는 데이터 소스에서 가져온 경우입니다. 데이터의 구조, 양 및 비율들은 모두 예측 가능하며, 패턴화되어 있는 경우가 많았습니다. 그러나 클라우드를 사용하면 애플리케이션 로그, 웹 애플리케이션, 모바일 장치, 소셜 미디어, IoT와 같이 제어가 잘되지 않거나 외부 소스와 같이 빠르게 증가하는 데이터를 활용하여 분석 업무를 수행해야 합니다. 데이터양만 증가하는 것이 아니라, 이 데이터의 형식은 방정형이거나 스키마가 없는 경우도 종종 존재합니다. 기존 EDW 솔루션은 이와 같은 새로운 변화로 인해 다양한 이슈가 발생하고 어려움을 겪고 있습니다. 이와 같은 어려움을 해소하기 위해 일부 EDW 시스템은 Hadoop 또는 Spark와 같은 빅데이터 플랫폼으로 전환되었습니다. 데이터 센터의 데이터 분석 기술은 오랜 기간동안 사용되면서 그 효용성은 입증 되었지만, 그 내면에는 플랫폼 개발 및 사용을 위한 엔지니어적인 접근법이 필요합니다. Snowflake의 클라우드 데이터 분석 플래폼의 접근법은 클라우드 환경에서 제공되는 경제성, 탄력성 및 확장성과 같은 이점을 그대로 활용하면서 동시에 기존 데이터 웨어하우스나 빅 데이터 플랫폼에서 수행되지 않는 새로운 유형의 워크로드나 유즈 케이스의 수용이 필요 할 수 있다는 것입니다. 그 때문에 Snowflake는 클라우드를 위한 새로운 데이터 분석 플랫폼을 구축하기로 결정했으며, 이 데이터 분석 플랫폼은 오늘날 클라우드 업체에서 제공되는 다양한 데이터 분석 플랫폼과 달리 Hadoop, PostrgreSQL과 같은 기존 기술을 기반으로 하지 않는다는 것입니다.
Snowflake의 주요 기능은 다음과 같습니다:
1) Pure SaaS Experience: 사용자는 분석 플랫폼 구축을 위해 물리적인 노드를 구매하거나 플랫폼 운영 관리자를 고용할 필요가 없습니다. 사용자는 클라우드에 존재하는 데이터나 가지고 있는 데이터를 클라우드로 업로드한 뒤, Snowflake에서 제공하는 GUI 또는 JDBC / ODBC와 같은 표준 인터페이스 기반으로 데이터에 바로 쿼리하여 사용할 수 있습니다. 다른 DBaaS(Databseses-a-Service) 제품과 달리 Snowflake의 서비스 측면은 전체 사용자 경험으로 확장 적용됩니다. 별도의 제품 튜닝 작업, 물리적인 노드 용량 산정, 아키텍터 설계, 스토리지 정리 작업은 Snowflake에서는 더이상 필요하지 않습니다.
2) Relational: Snowflake는 ANSI SQL 및 ACID 트랜잭션을 포괄적으로 지원합니다. 대부분 사용자는 변경 사항이 거의 없이 기존 워크로드를 Snowflake로 마이그레이션 할 수 있습니다.
3) Semi-Structured : Snowflake는 JSON, Avro와 같이 널리 사용되는 파일 형식을 지원하며, 반정형 데이터 가공 및 처리를 위한 내장 함수 및 SQL 확장 기능을 제공하고 있습니다. 자동 스키마 탐색 및 컬럼형 스토리지는 별도의 사용자 작업 없이 스키마가 없는 반정형 데이터에 대한 작업을 일반 관계형 데이터만큼 빠르게 처리할 수 있습니다.
4) Elastic : 스토리지 및 컴퓨팅 리소스는 데이터 가용성 또는 동시 쿼리 수행에 영향을 주지 않고 독립적으고 원활하게 확장될 수 있습니다.
5) Highly Avaliable: Snowflake는 소프트웨어 / 하드웨어 업그레이드 작업 중 다운 타임을 제공하지 않으며, 동시에 노드, 클러스터 및 데이터 센터 장애에 대한 고가용성을 보장합니다.
6) Durable: Snowflake는 의도되지 않은 데이터 손실에 대한 추가 보호 기능(Cloning, Undrop, Cross-region bakcup)을 통해 극도의 내구성을 제공하도록 설계되었습니다.
7) Cost-effiective: Snowflake는 모든 테이블 데이터를 압축하여, Compute 효율적인 아키텍처를 도입했습니다. 사용자는 실제 사용한 스토리지 및 컴퓨팅 리소스에 대해서만 비용을 지불하면 됩니다.
8) Secure: 임시파일 및 네트워크 트래픽을 포함한 모든 데이터는 종단-간 암호화되며, 역할 기반 접근 제어 기능을 통해 사용자는 SQL 수준에서 세분화된 접근 제어를 실행 할 수 있습니다.
Snowflake는 현재 Amazon 클라우드(AWS), Azure, GCP와 같은 다양한 퍼블릭 클라우드 환경을 모두 지원합니다.
1. STORAGE VERSUS COMPUTE
Shared-Nothing 아키텍처는 확장성과 범용 하드웨어라는 두 가지 주요 이유로 고성능 데이터 웨어하우징에서 지배적인 시스템 아키텍처가 되었습니다. Shared-Nothing 아키텍처에서 모든 실행 노드에는 자체 로컬 디스크가 있습니다. 테이블의 데이터는 노드 간에 수평으로 분할되며 개별 실행 노드는 로컬 디스크에 저장된 데이터만을 처리하도록 설계되었습니다. 이 설계 방식은 작은(브로드캐스트) 차원 테이블을 큰(분할된) 팩트 테이블과 조인하는 데 매우 적은 대역폭이 필요하기 때문에 스타 스키마 쿼리에 적합합니다. 그리고 공유 데이터(Shared-All) 구조나 하드웨어 리소스에 대한 경합이 거의 없기 때문에 값비싼 맞춤형 하드웨어가 필요하지 않습니다. 순수 Shared-Nothing 아키텍처에서 모든 노드는 요청받은 쿼리 수행 시, 동일한 책임을 가지며 동일한 하드웨어에서 실행됩니다. 이 접근 방식은 현존하는 데이터 플랫폼을 위한 모든 소프트웨어에서 채택되어 적용되었지만, 전통적인 Shared-Nothing 아키텍처에는 중요한 단점이 있습니다. 컴퓨팅 리소스와 스토리지 리소스를 긴밀하게 결합되어 특정 시나리오에서 문제를 발생시킵니다.
- 이기종 워크로드(Heterogeneous Workload): 하드웨어는 동종이지만 워크로드는 일반적으로 그렇지 않습니다. 대량 로드(높은 I/O 대역폭, 가벼운 컴퓨팅)에 이상적인 시스템 구성은 복잡한 쿼리(낮은 I/O 대역폭, 많은 컴퓨팅)에 적합하지 않으며 그 반대의 경우도 마찬가지입니다. 결과적으로 클러스터를 구성하는 여러 노드가 이기종 하드웨어로 구성된 경우, 성능이 낮은 하드웨어에서 측정되는 성능으로 하향 평준화가 됩니다.
- 맴버쉽(Membership) 변경: 특정 노드에 장애가 발생하거나, 관리자가 클러스터에 노드 추가/삭제하는 경우, 노드에 저장 보관된 데이터에 대한 재분배 작업을 수행해야 합니다. 클러스터의 노드는 데이터 셔플링과 쿼리 처리를 모두 담당하기 때문에, 이와 같은 상황이 발생한 경우에 성능에 많은 영향이 미치며, 탄력성과 가용성이 제한됩니다.
- 온라인 업그레이드: 클러스터에 소규모 노드의 변경 작업은 데이터 재분배 전략을 사용하여 어느 정도 완화할 수 있지만, 소프트웨어 및 하드웨어 업그레이드는 결국 시스템의 모든 노드에 영향을 미칩니다. 시스템 다운타임 없이 노드가 하나씩 업그레이드되도록 온라인 업그레이드를 구현하는 것은 원칙적으로 가능하지만 현실 세계에서는 매우 어렵습니다.
온-프레미스 환경에서 이러한 문제는 일반적으로 용인될 수 있습니다. 현실 세계의 워크로드 종류는 다양화되는 추세이지만, 실행 환경은 제한적이고 고정된 워크로드만을 수용하도록 구축되어 있기 때문입니다. 또한, 하드웨어 또는 소프트웨어 업그레이드 작업은 드물게 실행될 수밖에 없으며, 오류 및 클러스터 노드 조정도 마찬가지입니다. 하지만 클라우드는 온-프레미스와 매우 다릅니다. Amazone EC2와 같은 플랫폼에는 다양한 노드 유형이 있으며, 이를 활용하는 것은 매우 단순하고 간편하기 때문에 데이터를 올바른 유형의 노드를 선택하여 로드하면 됩니다. 노드 오류는 더 자주 발생 할 수 있으며, 동일한 유형의 노드 간에도 성능이 크게 다를 수 있습니다. 또한, 클라우드는 온라인 업그레이드와 탄력적 확장이 가능한 강력한 기능을 제공하고 있습니다. 온라인 업그레이드는 소프트웨어 개발 주기를 획기적으로 단축하고 가용성을 높여줍니다. 탄력적 확장은 가용성을 높이고 사용자가 일시적인 필요에 따라 리소스 소비를 조정할 수 있게 도와줍니다. 이러한 이유로 Snowflake는 스토리지와 컴퓨팅을 분리한 아키텍처를 체택하였습니다. 두 개의 계층은 느슨하게 연결되어 두 계층이 독립적으로 확장 가능한 서비스에 의해 처리됩니다. 컴퓨팅은 Snowflake 엔진을 통해 제공되며, 스토리지는 실행 환경에 따라 Amazone S3, Azure Blob Storage, GCS(Google Cloud Storage)를 통해 제공됩니다. 컴퓨팅 노드와 스토리지 노드 간의 네트워크 트래픽을 줄이기 위해 개별 컴퓨팅 노드는 로컬 디스크에 일부 테이블 데이터를 캐쉬 합니다. 이 솔루션의 추가 이점은 로컬 디스크 공간이 전체 기본 데이터를 복제하는 데 사용되지 않는다는 것입니다. 이 데이터는 매우 크고 쿼리 처리 시점에 대부분 사용되지 않을 수 있습니다. 대신 로컬 디스크는 임시 데이터 및 캐시 전용으로 사용되며 둘 다 핫 데이터로 취급됩니다. 우리는 이 새로운 아키텍처를 다중 클러스터 공유 데이터 아키텍처라고 합니다.
2. 아키텍처
Snowflake는 엔터프라이즈 서비스로 설계되었으며, 높은 수준의 사용성과 상호 운용성을 제공하는 것 외에도 가용성을 제공합니다. 이를 위해 Snowflake는 높은 내결함성과 독립적으로 확장 가능한 서비스로 구성된 서비스 지향 아키텍처를 채택하였으며, 이러한 서비스는 다음과 같은 세 가지 아키텍처 계층으로 구성되며, 개별 서비스는 RESTful 인터페이스를 통해 통신합니다.
1) Data Storage: 이 계층은 Amozon S3를 사용하여 테이블 데이터 및 쿼리 결과를 저장합니다.
2) Virtual Warehouse: 시스템의 근육의 역할을 담당합니다. 이 계층은 Virtual Warehose라는 가상 머신의 탄력적 클러스터 내에서 쿼리 실행을 처리합니다.
3) Cloud Service: 시스템의 두뇌 역할을 담당합니다. 이 계층은 Virtual Warehouse, 쿼리, 트랙잭션 및 이와 관련된 모든 메타데이터)데이터베이스 스키마, 접근 제어 정보, 암호화 키, 사용 통계 등)을 관리하는 서비스 모음입니다.
다음 그림은 Snowflake의 세 가지 아키텍처 계층과 주요 구성 요소를 보여줍니다.
2.1 데이터 스토리지
Snowflake를 개발하는 시점에 AWS는 클라우드 플랫폼 시장에서 가장 성숙한 제품을 제공하였고, 가장 많은 사용자들이 사용하고 있었기 때문에 초기 플랫폼으로 AWS를 선택하였습니다. 이제 두 번째 선택은 S3를 선택하거나 HDFS와 같은 오픈 소스 기반으로 자체 스토리지 서비스를 개발하는 것이었습니다. 초기 S3를 검증하는데 많은 시간을 투자했으며, S3의 성능은 상이할 수 있지만 사용성, 고가용성 및 강력한 내구성 보장은 HDFS와 같은 오픈 소스 기반으로 개발된 스토리지 엔진이 S3를 능가하기 어렵다고 판단하였습니다. 따라서 자체 스토리지 서비스를 개발하는 대신 로컬 캐싱에 더 많은 투자를 하기로 했습니다. 로컬 스토리지보다 S3는 일반적으로 액세스 대기 시간이 훨씬 더 길고 모든 단일 I/O 요청과 관련된 CPU 오버헤드가 더 높습니다. 특히 HTTPS 연결을 사용하는 경우에 그렇습니다. 그러나 더 중요한 것은 S3가 상대적으로 간단한 HTTP(S) 기반 PUT/GET/DELETE 인터페이스가 있는 BLOB 저장소라는 것입니다. 개체, 즉 파일은 전체(덮어쓰기)만 가능합니다. 파일 끝에 데이터를 추가하는 것도 불가능합니다. 실제로 파일의 정확한 크기는 PUT 요청에서 미리 알아야 합니다. 그러나 S3는 파일의 일부(범위)에 대한 GET 요청을 지원합니다. 이러한 속성은 Snowflake의 테이블 파일 형식과 동시 쿼리 제어에 큰 영향을 미쳤습니다. 테이블은 기존 데이터베이스 시스템의 블록 또는 페이지에 해당하는 크기로 파일로 수평으로 분할되며, 해당 파일을 변경할 수 없는 특성이 있습니다. 각 파일 내에서 개별 속성과 컬럼 값은 함께 그룹화되고 PAX 또는 하이브리드 컬럼 형식이라고 하는 잘 알려진 체계로 크게 압축됩니다. 각 테이블 파일에는 다른 메타 데이터 중에서 파일 내 각 컬럼의 오프셋이 포함된 헤더가 있습니다. S3는 파일의 일부에 대한 GET 요청을 허용하기 때문에 쿼리는 파일 헤더와 관심 있는 컬럼의 데이터만 다운로드하면 됩니다. Snowflake는 S3를 테이블 데이터 저장소 이상의 용도로 사용합니다. 예를 들어, 로컬 디스크 공간이 다 사용되는 경우 쿼리에 의해 생성된 임시 데이터와 대용량 쿼리 결과를 S3에 저장합니다. 즉, 임시 데이터를 S3에 저장할 수 있게 함으로써, 시스템이 메모리 부족 또는 디스크 부족으로 인한 오류 없이 임의의 큰 쿼리를 처리 할 수 있게 되었습니다. 또한, 쿼리 결과를 S3에 저장하면 기존 전통적인 데이터베이스 시스템에서 볼 수 있는 서버-사이드 커서가 불필요하기 때문에 새로운 형태의 클라이언트 상호 작용이 가능하고 쿼리 처리가 간소화됩니다. S3 파일, 통계, 잠금, 트랜잭션 로그 등으로 구성된 테이블, 즉 카탈로그 객체와 같은 메타데이터는 클라우드 서비스 계층에 확장 가능한 트랜잭션 키-값 저장소에 저장됩니다.
2.2 Virtual Warehouse
가상 웨어하우스(Virtual Warehouse) 계층은 EC2 인스턴스 클러스터로 구성됩니다. 이러한 개별 클러스터는 가상 웨어하우스(VW)라는 추상화를 통해 사용자에게 제공됩니다. VW를 구성하는 개별 EC2 인스턴스를 Worker node라 하며, 사용자는 Worker node와 직접 상호 작용하지 않습니다. 사실 사용자는 VW를 구성하는 Worker node나 Worker node의 수를 알지 못하거나 신경 쓸 필요가 없습니다. VW는 대신 X-Small에서 XX-Large와 같은 "T-셔츠 크기"로 실행 환경을 구성하면 됩니다.
2.2.1 Elasticity & Isolation
VW는 순전히 컴퓨팅 리소스입니다. 요청 시 언제든지 생성, 소멸 또는 크기 조정이 가능합니다. VW를 생성하거나 중지해도 데이터베이스 상태에는 영향을 미치지 않습니다. 사용자의 쿼리 요청이 없는 경우에는 모든 VW를 종료하는 것은 합리적이며 권장하는 방식입니다. 이러한 탄력성을 통해 사용자는 데이터 볼륨에 관계없이 컴퓨팅 리소스를 워크로드 유형에 맞게 동적으로 조정할 수 있습니다. 개별 쿼리는 정확히 하나의 VW에서 실행되며, Worker node는 VW 간에 공유되지 않기 때문에 완벽하게 격리된 실행 환경을 쿼리, 사용자 또는 워크로드에게 제공합니다(하지만 우리는 성능 격리가 큰 문제가 되지 않는 범위에서, 노드 활용도를 높이고 비용을 낮출 수 있는 옵션이기 때문에, Worker node 공유를 향후 중요한 작업 영역으로 생각하고 있습니다). 사용자가 새로운 쿼리를 Snowflake에 제출하면, 해당 VW의 개별 Worker node(또는 옵티마이저가 작은 쿼리를 감지하는 경우, 노드의 하위 집합)가 새 작업자 프로세스를 생성합니다. 개별 작업자 프로세서는 쿼리 기간 동안만 작동합니다. 작업자 오류는 쉽게 제어되고 재시도를 통해 일반적으로 해결됩니다. 각 사용자는 주어진 시간에 여러 VW를 실행할 수 있으며, 개별 VW는 차례로 여러 동시 쿼리를 처리할 수 있습니다. 모든 VW는 데이터를 물리적인 위치로 복사할 필요가 없이 동일한 공유 테이블에 접근할 수 있습니다. 공유 무제한 스토리지는 사용자가 DW의 핵심 원칙 중의 하나인 모든 데이터를 공유하고 통합할 수 있음을 의미하며, 동시에 사용자는 다양한 워크로드가 수행되고 있는 시점에도 다른 워크로드에 영향을 받지 않고 격리된 실행환경에서 자신의 분석 업무를 수행할 수 있습니다. Snowflake는 탄력성과 격리성이라는 클라우드 아키텍처 혜택을 그대로 계승하여 제공 할 수 있습니다. 1) 탄력성의 대표적인 예는 동일한 가격으로 더 좋은 성능을 달성할 수 있습니다. 예를 들어, 4개 노드에서 15시간 소요되는 데이터 로드 작업이 32개 노드의 시스템에서 2시간에 완료할 수 있다면, 컴퓨팅을 위해 지불해야 하는 가격은 유사하지만, 사용자 경험을 크게 개선할 수 있습니다. 즉, VW의 탄력성은 Snowflake 아키텍처의 가장 큰 이점이자 차별성이며, 클라우드의 고유한 기능을 사용하기 위해서 새로운 설계가 얼마나 중요한지를 보여주는 좋은 예시입니다.
2.2.2 Local Caching & File Stealing
개별 Worker node는 로컬 디스크에 테이블 데이터의 일부 내용을 캐시로 유지 관리합니다. 캐시는 노드가 과거에 접근한 테이블 파일, 즉 S3 객체의 모음이며, 정확히 말하면 쿼리가 필요한 컬럼 데이터를 다운로드하기 때문에 캐시는 파일 헤더와 파일의 개별 컬럼을 보유하고 있습니다. 캐시 데이터는 Worker node가 실행 중인 기간 동안 유지되며, 동시 및 후속 작업자 프로세스 간에 공유됩니다. 캐시는 LRU 알고리즘에 의해 관리 유지되며, 캐시 적중률을 개선하고 VW의 Worker node에서 개별 테이블 파일의 중복 캐싱을 피하고자 쿼리 최적화 프로그램은 테이블 파일에 대한 일관된 해싱을 사용하여 작업자 노드에 입력 파일 세트를 할당합니다. 따라서, 동일한 테이블 파일에 접근하는 후속 또는 동시 쿼리는 동일한 작업자 노드에서 이 캐시에서 제공하는 성능 혜택을 얻을 수 있습니다. Snowflake는 궁극적 일관성 해싱 알고리즘을 제공합니다. 즉, 노드 오류 또는 VW 크기 조정으로 인한 Worker node 셋이 변경되면 캐시의 데이터가 바로 분산되지 않습니다. 대신 Snowflake는 LRU 교체 정책에 따라 캐시 내의 데이터를 변경하는 작업을 수행할 때 궁극적으로 이뤄집니다. 이는 여러 쿼리에 대한 캐시 데이터를 변경하는 비용을 상각하여 노드 간의 많은 양의 데이터가 즉시 분배되어야 하는 Eager 캐시 또는 Shared-nothing 시스템보다 휠씬 좋은 가용성을 제공합니다. 또한 "degraded" 모드를 지원하지 않기 때문에 시스템 아키텍처를 더 단순화 할 수 있습니다. 캐싱 전략 이외에도 데이터 스큐 처리는 클라우드 데이터 플랫폼에서 매우 중요한 요소입니다. 일부 노드는 가상화 문제 또는 네트워크 경합으로 인해 다른 노드보다 더 느리게 요청받은 쿼리를 처리할 수 있습니다. Snowflake는 데이터 스캔 시점에 데이터 스큐에 관련된 이슈를 처리합니다. Worker 프로세스가 입력 파일 세트에 대한 데이터 스캔 작업을 완료할 때마다 피어로부터 추가 파일을 요청하며, 이를 "stealing(도용)"이라고 합니다. 피어가 관련된 요청을 처리할 때 마다 입력 파일 세트에 처리해야 할 파일들이 남아 있음을 발견하면, 현재 쿼리의 기간 및 범위에 대해 남은 파일들 중 하나의 소유권을 이전하여 요청으로 응답합니다. 그런 다음 요청자가 피어가 아닌 S3에 직접 파일을 다운로드하여 데이터 스큐에 관련된 이슈를 해결합니다. 이 설계 개념은 파일 도용(Strealing)이 부하가 집중된 노드에 추가 부하를 조정하여 추가 성능 저하 현상을 제거하는 용도로 활용됩니다.
2.2.3 Execution Engine
다른 데이터베이스 시스템이 10개 노드를 사용하여 동시 쿼리를 수행할 수 있다면, 1,000개 이상의 노드에서 쿼리를 실행 할 수 있다는 것은 확장성을 제외하고는 큰 차별성을 제공하지 않습니다. 확장성도 중요하지만, 노드당 효율성도 마찬가지로 중요하기 때문에, Snowflake는 현존하는 데이터베이스 중 최고의 가격/성능을 제공하기를 원했기 때문에 새로운 최첨단 SQL 실행 엔진을 구현하기로 했습니다. Snowflake 실행 엔진은 1) 컬럼형, 2) 벡터화 및 3) 푸시-기반으로 설계되었습니다:
- Columnar : 컬럼형 데이터 저장 및 실행은 CPU 캐시 및 SIMD 명령을 보다 효율적으로 사용하고 압축을 통한 추가 해택을 얻을 수 있기 때문에 일반적으로 분석 워크로드에 대해 행-단위 저장 및 처리보다 우수합니다.
- Vectorized : 벡터화된 실행은 예를 들어 MR와 달리 Snowflake에서 중간 처리 결과를 Serialization 하지 않는다는 것을 의미합니다. 대신, 데이터는 컴럼 형태의 수천 행 배치로 파이프라인 방식으로 처리됩니다. Vector-Wise(MonetDB/X100)가 최초로 고안한 이 접근 방식은 I/O를 절약하고 캐시 효율성을 극대화하여 성능을 개선할 수 있습니다.
- Push- based : 푸시 기반 실행은 관계 연산자가 데이터를 가져오기를 기다리지 않고 관계 연산자가 결과를 다운스트림 연산자에게 푸시한다는 사실을 의미합니다(고전적인 화산 스타일 모델). 푸시 기반 실행은 긴밀한 루프에서 제어 흐름 논리를 제거하기 때문에 캐시 효율성을 향상시킵니다. 또한 Snowflake는 트리가 아닌 DAG 형태의 계획을 효율적으로 처리하여 중간 결과를 공유하고 파이프라인 할 수 있는 추가 기능을 제공합니다.
주목해야 하는 점은 Snowflake에는 전통적인 쿼리 엔진에서 구현된 오버헤드에 관련된 소스를 구현하지 않았다는 것입니다. 특히, 엔진에서 처리해야 하는 쿼리는 변경되지 않는 파일 집합에 대해서만 실행되기 때문에 Snowflake 엔진은 쿼리 처리 중 트랜잭션 관리를 필요로 하지 않습니다. 또한, 데이터 플랫폼 내의 대부분의 쿼리는 많은 양의 데이터를 스캔하여 처리하는 속성을 가지고 있습니다. 이처럼 많은 양의 데이터를 처리할 때 테이블 버퍼링 영역으로 메모리를 사용하는 것은 바람직하지 않은 접근 방식입니다. 이러한 속성을 기반하여 Snowflake는 버퍼 풀이 구현하지 않았고, 모든 주요 연산 작업(Join, Group by, Sort)에 대해 메모리 용량을 벗어나는 경우 디스크 사용을 허용하도록 구현하였습니다. 일반적으로 메모리를 사용하는 경우 쿼리 처리 엔진이 더 가볍고 더 빠를 수 있지만, 대용량 데이터를 처리해야 하는 워크로드에 대해서는 매우 제한적인 것도 사실입니다. 분석 워크로드에는 매우 큰 조인 또는 집계 워크로드가 포함되어 있기 때문에 Snowflake 처리 엔진을 설계할 때 모든 조건을 다 고려하였습니다.
2.3 Cloud Services
가상 웨어하우스(VW)는 임시적인 사용자별 리소스이지만, 이와 대조적으로 클라우드 서비스 계층은 멀티-테넌트기반으로 구현된 글로벌 서비스입니다. 이 계층의 개별 서비스(액세스 제어, 쿼리 최적화 프로그램, 트랜잭션 관리자 등)는 항상 사용 가능해야 하며, 많은 사용자들에게 공유되어야 합니다. Snowflake Cloud Service의 목표는 멀티-테넌시는 활용도를 높이고 관리 오버헤드를 줄여 모든 사용자가 완전히 개인용 시스템을 구현하는 기존 아키텍처보다 더 개선된 서비스를 제공하는 것입니다. Cloud Service의 개별 서비스는 고가용성과 확장성을 위해 복제 구성되어 있어서, 실행 중인 일부 쿼리는 실패할 수 있지만(투명하게 다시 실행될 수 있음), 개별 서비스 노드의 오류로 인해 데이터 손실 또는 가용성 손실이 발생하지 않도록 구현되어 있습니다.
2.3.1 Query Management and Optimization
사용자가 발행한 모든 쿼리는 Snowflake의 클라우드 서비스 계층을 통과해야 합니다. 이 계층에서는 쿼리 수명 주기에 관련된 모든 작업이 수행됩니다(SQL 문 분석, 접근제어 및 SQL Plan 최적화 등). Snowflake의 쿼리 최적화 프로그램은 비용 기반의 최적화와 함께 일반적인 Cascades-style 접근 방식을 따릅니다. 최적화에 사용된 모든 통계는 데이터 로드 및 업데이트 시 자동으로 유지됩니다. Snowflake는 인덱스를 사용하지 않기 때문에 SQL Plan 검색을 위한 디스크는 다른 시스템보다 작습니다. 또한, Plan 디스크 공간은 가급적 많은 단계(예를 들면 조인용 데이터 분산 유형 선정)를 실행 시점으로 연기함으로써 더 절감시킬 수 있습니다. 이 설계는 최대 성능 관점에서는 약간의 손실을 감수하지만, 옵티마이저가 내리는 잘못된 결정의 수를 줄여서 견고성을 높이는 데 도움을 줍니다. 또한, 서비스 경험에 대한 Snowflake의 전반적인 초점과 일치하는 시스템을 더 쉽게 사용할 수 있습니다(성능 예측 가능). 최적화 프로그램이 완료되면 결과 실행 계획이 쿼리의 일부인 모든 작업자 노드에 배포됩니다. 쿼리가 실행되면 Cloud Services는 쿼리 상태를 지속적으로 추적하여 성능 메트릭을 수집하고 노드 오류를 감지합니다. 모든 쿼리 정보 및 통계는 감사 및 성능 분석을 위해 저장되며, 사용자는 Snowflake GUI를 통해 과거 및 진행 중인 쿼리를 모니터링하고 분석할 수 있습니다.
2.3.2 Concurrency Control
앞에서 언급했듯이 동시성 제어는 전적으로 클라우드 서비스 계층에서 처리됩니다. Snowflake는 분석 워크로드 용으로 설계되었으며, 대부분의 다른 시스템과 마찬가지로 Snowflake는 SI(Snapshot Isolation)를 통해 ACID 트랜잭션을 구현하기로 했습니다. SI에서 트랜잭션의 모든 읽기 작업은 트랜잭션이 시작된 시점을 기준으로 데이터베이스의 일관된 스냅샷에서 해당 데이터를 읽어 들입니다. SI는 MVCC(다중 버전 동시성 제어) 위에 구현됩니다. 즉, 변경된 모든 데이터베이스 개체의 복사본이 일정 기간 동안 보존됩니다. MVCC는 테이블 파일이 변경 불가능하다는 것과, 스토리지 계층으로 S3를 사용한다는 사실을 감안할 때 자연스러운 선택입니다. 파일에 대한 변경은 변경 사항을 포함한 다른 파일로 교체해야만 가능하기 때문에, 테이블에 대한 쓰기 작업(삽입, 업데이트, 삭제, 병합)은 이전 테이블 버전과 관련된 전체 파일을 추가 및 제거하여 새 버전의 테이블을 생성합니다. 파일 추가 및 제거는 특정 테이블 버전에 속하는 파일 집합을 매우 효율적으로 계산할 수 있는 형식으로 메타데이터(글로벌 키-값 저장소)에서 추적됩니다. SI 외에도 Snowflake는 이러한 스냅샷을 사용하여 시간 여행과 데이터베이스 개체의 효율적인 복제를 구현합니다.
2.3.3 Pruning
요청받은 쿼리와 관련된 데이터에만 접근을 제한하는 방식은 쿼리 성능을 개선할 수 있는 하나의 방식이며, 대부분 데이터베이스의 데이터 접근은 B+ 트리 또는 이와 유사한 데이터 구조 형태의 인텍스 사용을 통해 구현되었습니다. 이 접근 방식은 트랜잭션 처리에 매우 효과적인 것으로 입증되었지만, Snowflake와 같이 대용량 데이터 분석 플랫폼에는 여러 문제를 야기시킵니다. 첫 번째 문제는, 임의 접근 처리는 저장 방식(S3)과 데이터 형식(압축 파일) 모두에 문제가 있습니다. 두 번째는, 인덱스를 유지하면 데이터양과 데이터 로드 시간이 크게 증가됩니다. 마지막 문제는 사용자가 명시적으로 인덱스를 생성해야 합니다. 이는 Snowflake의 서비스 접근 방식과 매우 상이한 방식이며, 일반적으로 인덱스를 유지 관리하는 것은 비용이 많이 들고 관리하기 매우 복잡한 작업을 동반합니다. 최근 대규모 데이터 처리에 대해 min-max pruning, 소규모의 materialized 집계, zone map, data skipping으로 알려진 대안 기술이 인기를 얻고 있습니다. 여기서 시스템은 주어진 데이터 청크(레코드, 파일, 블록 등의 세트), 특히 청크 내의 최소값 및 최대값에 대한 데이터 배포 정보를 유지 관리합니다. 예를들어, 파일 f1과 f2가 일부 열 x에 각 값 3...5와 4....6을 포함한다고 가정합니다. 그런 다음 쿼리에 WHERE x >= 6이라는 조건이 있으며, 파일 f2에만 접근해야 한다는 것을 알 수 있습니다. 기존 인덱스와 달리 이 메타데이터는 일반적으로 실제 데이터보다 휠씬 작기 때문에 스토리지 오버헤드가 적고 엑세스가 빠릅니다. Pruning은 Snowflake 설계 원칙과 일치합니다; 사용자 입력에 의존하지 않지 않고, 잘 확장되며, 유지 관리가 용이합니다. 또한, 대용량 데이터 청크의 순차적 접근에도 적합하지만, 데이터 로드, 쿼리 최적화 및 쿼리 실행 시간에는 약간의 오버헤드가 추가됩니다. Snowflake는 모든 테이블 파일에 대해 Pruning과 관련된 메타데이터를 유지합니다. 메타 데이터는 일반 관계형 컬럼 뿐만 아니라 반정형 데이터 내부의 자동 감지된 데이터-셋도 대상이 됩니다. 요청받은 쿼리에 대한 최적화 작업을 수행하는 동안, 쿼리 조건자에 대해 메타데이터를 확인하여 쿼리 실행을 위한 입력 파일의 개수를 줄입니다. 옵티마이저는 단순한 값(value)기반의 조건절뿐만 아니라 "WEEKDAY(orderdate) IN (6, 7)"와 같은 복잡한 표현식에 대해서도 Pruning을 수행합니다. Static Pruning 외에도 Snowflake는 실행 시점에 Dynamic Pruning을 수행합니다. 예를 들어, 해시 조인 처리의 일부로 Snowflake는 빌드 측 레코드의 조인 키 배포에 대한 통계를 수집하며, 그런 다음 이 정보는 프로브 측으로 푸시되어 프로브 측에서 전체 파일을 필터링하고 건너뛸 수 있습니다. 이것은 블룸 조인과 같은 다른 잘 알려진 기술에 추가됩니다.
3. 기능 요약
Snowflake는 포괄적인 SQL 지원, ACID 트랜잭션, 표준 인터페이스, 안정성 및 보안, 고객 지원, 물론 강력한 성능 및 확장성 등 관계형 데이터 웨어하우스에서 기대하는 많은 기능을 제공하고 있으며, 전통적인 데이터 플랫폼에서 제공하지 못했던 여러 가지 유용한 기능을 추가로 제공하고 있습니다. 이 섹션에서는 Snowflake 만이 지원하는 기술적 차별화 기능에 대한 내용을 설명합니다.
3.1 Pure Software-as-a-Service Experience
Snowflake는 표준 데이터베이스 인터페이스(JDBC, ODBC, Python PEP-0249)를 지원하며 Tableau, Informatica 또는 Looker와 같은 다양한 3rd 도구 및 서비스를 공식적으로 지원합니다. 이와 별개로, Snowflake는 웹 브라우저만 사용하여 시스템과 상호 작용할 수 있는 기능도 함께 제공하고 있습니다. GUI는 사소해 보일 수 있지만 중요한 차별 요소입니다. GUI를 사용하면 모든 위치와 환경에서 Snowflake에 매우 쉽게 접속 할 수 있기 때문에 데이터 플랫폼 사용에 대한 복잡성을 크게 줄여줄 수 있습니다. 클라우드에 이미 많은 데이터가 있기 때문에, 많은 사용자들은 별도의 소프트웨어를 다운로드하지 않고 클라우드 상에 존재하는 데이터를 대상으로 Snowflake를 활용하여 분석 업무를 자유롭게 수행할 수 있습니다. 또한, Snowflake에서 제공하는 GUI는 SQL 작업뿐만 아니라 데이터베이스 카탈로그, 사용자 및 시스템 관리, 모니터링, 사용 정보 등에 관련된 정보를 제공합니다. Snowflake는 온라인 협업, 사용자 피드백 및 지원 등과 같은 다양한 측면에 대해서 지속해서 GUI 기능을 개선하고 있습니다. 그러나 사용 용이성과 서비스 경험에 대한 우리의 초점은 사용자 인터페이스에 제한되지 않고, 시스템 아키텍처의 모든 측면으로 확장 적용됩니다. 즉, 장애 관리, 별도의 튜닝 작업, 플랫폼에 대한 물리적인 아키텍처 설계, 스토리지 정리와 같은 고된 작업이 Snowflake에서는 더 이상 필요로 하지 않습니다.
3.2 Continuous Availability
과거에 데이터 웨어하우징 솔루션은 대다수 백엔드 시스템이었습니다. 이러한 환경에서 계획된(소프트웨어 업그레이드 또는 관리 작업) 다운타임과 계획되지 않은(장애) 다운타임은 일반적으로 운영에 큰 영향을 미치지 않았지만, 오늘날 데이터 분석이 점점 더 많은 비즈니스 작업에 중요해짐에 따라 지속적인 가용성은 모든 데이터 웨어하우스에서 중요한 요구 사항이 되었습니다. 이 추세는 최신 SaaS 시스템에 대한 기대치를 반영하며, 대부분은 (계획된) 다운타임이 허용하지 않는 시스템을 요구하고 있습니다. Snowflake는 시장과 고객의 요구사항을 충족하는 가용성을 제공합니다. 이와 관련하여 두 가지 주요 기술 기능은 장애 복구 및 온라인 업그레이드입니다.
3.2.1 Fault Resilience
Snowflake는 그림 2와 같이 아키텍처의 모든 수준에서 개별 및 상관된 노드 장애를 허용하도록 설계되어 있습니다. Snowflake의 데이터 스토리지 계층은 S3이며 Amazon 용어로 "가용 영역" 또는 AZ라고 하는 여러 데이터 센터에 복제됩니다. AZ 간 복제를 통해 S3는 전체 AZ 장애를 처리하고 99.99% 데이터 가용성과 99.999999999% 내구성을 보장할 수 있습니다. S3의 아키텍처와 일치하는 Snowflake의 메타데이터 저장소도 여러 AZ에 분산 및 복제됩니다. 노드가 실패하면 다른 노드가 최종 사용자에게 큰 영향을 미치지 않고 연속된 작업을 시작할 수 있습니다. 클라우드 서비스 계층의 나머지 서비스는 여러 AZ에 있는 stateless 노드로 구성되며 로드 밸런서는 이들 사이에 사용자 요청을 배포합니다. 따라서 단일 노드 오류 또는 전체 AZ 오류가 시스템 전체에 영향을 미치지 않으며, 현재 오류가 발생한 노드에 연결된 사용자에 대한 일부 실패한 쿼리가 발생할 수 있습니다. 이러한 사용자는 다음 쿼리를 위해 다른 노드로 리디렉션됩니다. 이와 대조적으로 가상 웨어하우스(VW)는 성능상의 이유로 여러 AZ에 분산되지 않습니다. 높은 네트워크 처리량은 분산 쿼리 실행에 매우 중요하며 네트워크 처리량은 동일한 AZ 배포 아키텍처가 훨씬 더 높습니다. 쿼리 실행 중에 Worker node 중 하나가 실패하면 쿼리는 실패하지만, 노드가 즉시 교체되거나 일시적으로 감소된 노드 수로 투명하게 다시 실행됩니다. 노드 교체를 가속화하기 위해 Snowflake는 Standby 노드의 작은 풀을 유지 관리합니다. (이 노드는 빠른 VW 프로비저닝에도 사용됩니다.) 하지만 전체 AZ를 사용할 수 없게 되면 해당 AZ의 지정된 VW에서 실행 중인 모든 쿼리가 실패하고 사용자는 다른 AZ에서 VW를 적극적으로 다시 프로비저닝해야 합니다.
3.2.2 Online Upgrade
Snowflake는 장애가 발생한 경우뿐만 아니라 소프트웨어 업그레이드 중에도 지속적인 가용성을 제공합니다. Snowflake는 Cloud Service 구성 요소와 VW에 대해서 여러 버전을 배포(side-by-side)하여 사용 할 수 있도록 설계되었습니다. 이는 모든 서비스가 실제로 stateless 상태라는 사실에 의해 가능합니다. 모든 상태 정보는 트랜잭션 키-값 저장소에 보관되며 메타데이터 버전 관리 및 스키마 진화를 처리하는 매핑 계층을 통해 액세스됩니다. 메타데이터 스키마를 변경할 때마다 이전 버전과의 하위호환성을 보장합니다. 소프트웨어 업그레이드를 수행하기 위해 Snowflake는 먼저 이전 버전과 함께 새 버전의 서비스를 배포합니다. 그런 다음 사용자 계정은 새 버전으로 점진적으로 전환되며, 신규 버전으로 전환된 사용자가 발행한 모든 새 쿼리는 새 버전으로 전달되어 처리됩니다. 이전 버전에 대해 실행되었던 모든 쿼리는 완료될 때까지 이전 버전에서 실행됩니다. 모든 쿼리와 사용자가 이전 버전 사용을 마치면 해당 버전의 모든 서비스가 이전 버전의 실행이 완료되고 이전 버전은 사용 중지됩니다. 그림 3은 진행 중인 업그레이드 프로세스의 스냅샷을 보여줍니다. 예를 들어, Snowflake에는 버전 1 및 버전 2의 두 가지 버전이 나란히 실행됩니다. 클라우드 서비스의 단일 구현에는 두 가지 버전이 있으며 각각 두 가지 버전이 있는 두 개의 가상 웨어하우스(VW)를 제어합니다. 로드 밸런서는 들어오는 호출을 적절한 버전의 Cloud Services로 보냅니다. 한 버전의 클라우드 서비스는 일치하는 버전의 VW와만 통신합니다. 앞서 언급했듯이 두 버전의 클라우드 서비스는 동일한 메타데이터 저장소를 공유합니다. 또한 서로 다른 버전의 VW가 동일한 Worker node와 캐시를 공유할 수 있습니다. 결과적으로 소프트웨어 업그레이드 후, 캐시를 재생성할 필요가 없으며, 전체 프로세스의 다운 타임이나 성능 저하 없이 새로운 버전을 사용자에게 투명하게 제공합니다. 온라인 업그레이드는 소프트웨어 개발 속도와 Snowflake에서 중요한 버그를 처리하는 방법에 엄청난 영향을 미쳤습니다. Snowflake는 일주일에 한 번씩 시스템 업그레이드 작업을 수행합니다. 즉, 매주 기능과 개선 사항을 릴리스합니다. 업그레이드 프로세스가 사용자에게 미치는 영향도를 최소화하고 원활하게 진행되도록 하기 위해 Snowflake는 별도의 운영 환경에서 업그레이드와 다운그레이드가 지속해서 테스트 됩니다. 매우 드물게 운영 환경에서 치명적인 버그를 발견한 경우(업그레이드 중일 필요는 없음), 이전 버전으로 매우 빠르게 다운그레이드하거나 수정 사항을 구현하고 예정 외 업그레이드를 수행할 수도 있습니다. 업그레이드/다운그레이드 메커니즘을 지속해서 테스트하고 실행하기 때문에 이 프로세스는 운영 환경에 영향도가 거의 없습니다.
3.3 Semi-Structured and Schema-Less Data
Snowflake는 반정형 데이터에 대해 VARIANT, ARRAY 및 OBJECT의 세 가지 타입을 사용해 표준 SQL에서 활용될 수 있습니다. VARIANT 타입의 값은 기본 SQL 유형(DATE, VARCHAR 등)의 모든 값과 가변 길이 값의 ARRAY 및 문자열에서 VARIANT 값으로 매핑되는 JavaScript와 같은 OBJECT를 저장할 수 있습니다. ARRAY 및 OBJECT는 VARIANT 타입의 유형이며, 내부적으로는 동일하게 구현되었습니다. 즉, 빠른 키-값 조회는 물론 효율적인 타입 테스트, 비교 및 해싱을 지원하는 자체 바이너리 직렬화입니다. 따라서 VARIANT 컬럼은 다른 열과 마찬가지로 조인 키, 그룹화 키 및 순서 지정 키로 사용할 수 있습니다. VARIANT 유형을 사용하면 Snowflake를 기존 ETL(Extract-Transform-Load) 방식이 아닌 ELT(Extract-Load-Transform) 방식으로 사용할 수 있습니다. 문서 스키마를 지정하거나 로드 시 변환을 수행할 필요가 없습니다. 사용자는 JSON, Avro 또는 XML 형식의 입력 데이터를 VARIANT 열에 직접 로드할 수 있습니다. Snowflake는 구문 분석 및 유형 추론을 처리합니다. Snowflake에서 지원되는 반정형 데이터에 대한 "Schema later" 접근 방식은 정보 생산자와 정보 소비자 및 중개자를 분리함으로써 스키마 진화를 가능하게 합니다. Snowflake에서 지원하는 schema resolution 방식을 사용하지 못하는 기존 데이터베이스의 경우, ETL 파이프라인에서 데이터 스키마를 변경하려면 여러 부서 간의 데이터 표준화에 대한 조정이 필요하며 실행하는 데 몇 달이 소요될 수도 있습니다. ELT과 Snowflake의 또 다른 장점은 나중에 변환이 필요한 경우 일반적으로 누락되거나 누락된 조인, 정렬, 집계, 복잡한 술어 등과 같은 작업을 포함하여 병렬 SQL 데이터베이스의 모든 기능을 사용하여 수행할 수 있다는 것입니다. 기존 ETL 도구 체인에서는 비효율적입니다. 그런 점에서 Snowflake는 완전한 JavaScript 구문과 VARIANT 데이터 유형과의 통합을 포함하는 절차적 사용자 정의 함수(UDF)를 제공합니다. 절차적 UDF에 대한 지원은 Snowflake에 배포되어 운영되는 ETL 작업의 수를 더욱 증가시킵니다.
3.3.1 Post-relational Operations
반정형 Document 데이터를 처리하는 데 가장 중요한 오퍼레이션은 필드 이름(OBJECT의 경우) 또는 오프셋(ARRAY의 경우)으로 데이터 요소를 추출하는 것입니다. Snowflake는 SQL 구문 또는 JavaScript와 유사한 경로 구문을 통해 반정형 데이터에서 데이터 추출 작업을 수행할 수 있습니다. 내부 인코딩은 데이터값을 추출하는 작업을 매우 효율적으로 수행합니다. 자식 요소는 부모 요소 내부의 포인터일 뿐이며, 별도의 데이터 복사가 필요하지 않습니다. 추출 후에는 결과 VARIANT 값을 표준 SQL 유형으로 캐스트하는 경우가 많습니다. 즉, 인코딩은 이러한 캐스트를 매우 효율적으로 만듭니다. 두 번째 일반적인 오퍼레이션은 병합, 즉 중첩된 문서를 여러 행으로 피벗하는 것입니다. Snowflake는 SQL lateral view를 사용하여 병합 작업을 수행합니다. 이 flattening 작업은 재귀적일 수 있음으로 반정형 문서의 계층 구조를 SQL 처리가 가능한 관계형 테이블로 완전히 변환할 수 있습니다. 병합의 반대 작업은 집계입니다. Snowflake는 이를 위해 ARRAY_AGG 및 OBJECT_AGG와 같은 몇 가지 새로운 집계 및 분석 함수를 제공하고 있습니다.
3.3.2 Columnar Storage and Processing
반정형 데이터에 직렬화(바이너리) 처리를 사용하는 것은 반정형 데이터를 관계형 데이터베이스에 통합하기 위한 일반적인 설계 전략입니다. 불행하게도 반정형데이터를 일반 관계형 데이터로 변환하는 접근법은 컬럼형 관계 데이터보다 데이터 저장 및 처리 효율성을 떨어뜨립니다. Cloudera Impala(Parquet 사용)와 Google Dremel은 반구조화된 데이터의 컬럼형 저장이 가능하고 유익하다는 것을 입증하였습니다. 그러나 Impala와 Dremel(및 외부화 BigQuery)은 사용자가 컬럼형 저장을 위한 완전한 테이블 스키마를 제공할 것을 필요로 하고 있습니다. 스키마 없는 직렬화 표현의 유연성과 컬럼형 기반 관계형 데이터베이스의 성능을 모두 달성하기 위해 Snowflake는 유형 추론 및 컬럼형 기반 스토리지에 대해 새롭고 자동화된 접근 방식을 도입했습니다. 이전에 언급했듯이 Snowflake는 하이브리드 컬럼 형식으로 데이터를 저장합니다. 반정형 데이터를 저장할 때 시스템은 자동으로 단일 테이블 파일 내의 문서 모음에 대한 통계 분석을 수행하여 자동 유형 추론을 수행하고 어떤(입력된) 경로가 자주 사용되는지 확인합니다. 그런 다음 해당 컬럼이 문서에서 제거되고 기본 관계형 데이터와 동일한 압축 컬럼 형식을 사용하여 별도로 저장됩니다. 이러한 컬럼의 경우 Snowflake는 일반 관계형 데이터와 마찬가지로 Pruning에 사용할 구체화된 집계도 계산합니다. 스캔하는 동안 다양한 열을 VARIANT 유형의 단일 열로 재조립할 수 있습니다. 그러나 대부분의 쿼리는 원본 문서의 컬럼 하위 집합에만 관심이 있습니다. 이러한 경우 Snowflake는 투영 및 캐스트 표현식을 스캔 연산자로 푸시하므로 필요한 컬럼만 액세스하고 대상 SQL 유형으로 직접 캐스트 됩니다. 위에서 설명한 최적화는 모든 테이블 파일에 대해 독립적으로 수행되므로 스키마 진화에서도 효율적인 저장 및 추출이 가능합니다. 그러나, 특히 pruning과 관련된 쿼리 최적화 측면에 문제가 발생할 소지가 있습니다. 경로 표현식에 관련된 술어가 있는 쿼리가 데이터 스캔할 파일을 제한하기 위해 pruning을 사용한다고 가정해 보도록 하겠습니다. 경로와 관련된 컬럼은 대부분의 경우 파일로 표현될 수 있지만, 간혹 파일의 메타정보를 참조해야 하는 경우도 발생할 수 있습니다. 보수적인 접근법은 적절한 메타정보가 없기 때문에 모든 데이터 파일을 스캔 처리해야 합니다. Snowflake는 반정현 문서 데이터에 포함된 모든 경로에 대해 Bloom filter를 계산하여 관련된 성능을 개선하였습니다. 이러한 Bloom filter는 다른 메타정보와 함께 저장되기 때문에 pruning 작업 중에 쿼리 최적화에 의해 참조되어 사용됩니다. 즉, 요청받은 쿼리에 필요하지 않는 테이블 파일은 스킵되어 처리됩니다.
3.3.3 Optimistic Conversion
일부 내장현 SQL 타입, 특히 data/time 값은 JSON 또는 XML과 같은 형식에서는 String으로 표현되기 때문에, 이러한 값은 쓰기(Insert / Update) 또는 읽기(select)작업에서 실제 데이터 유형으로 변환해야 합니다. 스키마 작업 또는 관련된 Hint가 없으면, 이와 관련된 값은 쿼리 수행 시점에 형변환을 수행해야 하므로 비 효율적인 방식입니다. 또 데이터 타입이 수행되지 않은 데이터의 다른 문제는 pruning을 작업에서 메타 정보를 활용하지 못하는 점입니다(특히, date 타입). 실제 사용자 환경에서는 date 컬럼의 값을 쿼리의 조건절로 활용합니다. 그러나, 형변환을 데이터 입력 시점에 적용하는 경우, 자동 형변환으로 인해 데이터 유실이 발생할 수도 있습니다. 예를 들어, numeric product 식별자를 포함한 필드는 number 유형이 아니라 string 값일 수도 있기 때문에 0의 값이 무시되어 처리될 수도 있습니다. 마찬가지로, date로 표현된 값이 string일 수도 있습니다. Snowflake는 원본과 형변환된 모든 데이터를 보존하는 optimistic data conversion을 수행하여 이와 같은 문제를 해결 할 수 있습니다. 이 기능을 통해 사용자는 원본 데이터를 필요한 경우 쉽게 검색하여 데이터를 재처리 할 수 있으며, 사용되지 않는 컬럼은 로드하지 않기 때문에 위의 이중 저장소로 인한 성능 영향도를 최소화 할 수 있습니다.
3.4 Time Travel and Cloning
앞서 Snowflake가 MVCC(Multi-version concurrency control)기반으로 SI(Snapshot Isolation)를 구현한 방식에 관해 설명했습니다. 테이블에 대해 쓰기 작업(insert, update, delete, merge)은 관련된 전체 파일을 추가 또는 제거하여 테이블의 최신 버전에 대한 데이터 파일을 생성하도록 구현되어 있습니다. Snowflake에서는 데이터 변경 작업에 의해 제거된 파일은 Retention 기간(최대 90일) 동안 내부적으로 보관됩니다. 파일 Retention 기능을 통해 Snowflake에서 Time traveling이라는 기능을 통해, 이전 버전의 데이터를 효율적으로 활용할 수 있습니다. 즉, 사용자는 AT 또는 BEFORE 구문을 사용한 SQL문을 통해 이 기능을 활용할 수 있습니다.
SELECT * FROM my_table AT(TIMESTAMP => ’Mon, 01 May 2015 16:20:00 -0700’::timestamp); SELECT * FROM my_table AT(OFFSET => -60*5); -- 5 min ago SELECT * FROM my_table BEFORE(STATEMENT => ’8e5d0ca9-005e-44e6-b858-a8f5b37c5726’);
단일 쿼리에서 동일한 테이블의 다른 버전 데이터에 대해서도 액세스할 수도 있습니다.
SELECT new.key, new.value, old.value FROM my_table new JOIN my_table AT(OFFSET => -86400) old -- 1 day ago ON new.key = old.key WHERE new.value <> old.value;
Snowflake는 동일한 기본 메타데이터를 기반으로 UNDROP 키워드를 도입하여 실수로 삭제된 테이블, 스키마 또는 전체 데이터베이스를 빠르게 복원할 수 있는 기능도 제공하고 있습니다.
DROP DATABASE important_db; -- whoops! UNDROP DATABASE important_db;
Snowflake는 또한 "CLONE" 키워드로 표현되는 복제(cloning)이라는 함수를 제공합니다. 테이블을 클로닝하면 테이블의 데이터 파일을 복사하지 않고 동일한 스키마와 데이터를 가진 신규 테이블을 빠르게 생성할 수 있습니다. 즉, 복제 오퍼레이션은 테이블의 데이터를 복사하고 신규 스키마를 생성하는 것이 아닌, 소스 테이블의 메타 정보를 복사하여 신규 테이블을 생성하는 것을 의미합니다. 테이블에 대한 복제 작업을 한 뒤, 두 테이블은 동일한 데이터 파일을 참조하지만, 두 테이블은 독립적으로 데이터를 수정할 수 있습니다. Snowflake는 Table이 아닌 스키마, 데이터베이스에 대해서도 Clone 기능을 지원하기 때문에 효율적으로 스냅샷 작업을 수행할 수 있습니다. 대규모 배치 또는 오래 소요되는 데이터 분석 작업전에 스냅샷을 수행하는 것을 권장합니다. 또한, CLONE 키워드는 AT 또는 BEFORE 구문과 함께 사용할 수 있기 때문에 스냅샷을 특정 오퍼레이션 이후에도 수행할 수 있습니다.
CREATE DATABASE recovered_db CLONE important_db BEFORE( STATEMENT => ’8e5d0ca9-005e-44e6-b858-a8f5b37c5726’);
3.5 Security
Snowflake는 클라우드 플랫폼을 포함하여 아키텍처의 모든 수준에 대한 공격으로부터 사용자 데이터를 보호하도록 설계되었습니다. 이를 위해 Snowflake는 2단계 인증, (클라이언트 측) 암호화된 데이터 가져오기 및 내보내기, 안전한 데이터 전송 및 저장, 데이터베이스 객체에 대한 RBAC(역할 기반 액세스 제어)를 구현합니다. 항상 데이터는 네트워크를 통해 전송되기 전과 로컬 디스크 또는 공유 저장소에 쓰기 전에 암호화됩니다(S3). 따라서 Snowflake는 완전한 종단 간 데이터 암호화 및 보안을 제공합니다.
3.5.1 Key Hierarchy
Snowflake는 AWS CloudHSM에 기반을 둔 계층적 키 모델과 함께 강력한 AES 256 암호화 방식을 사용합니다. 암호화 키는 NIST 800-57 암호화 키 관리 수명 주기를 준수하도록 자동으로 교체되고 암호화됩니다. 암호화 및 키 관리는 사용자에게 전체적으로 투명화된 방식으로 진행되기 때문에 추가 구성 및 관리가 불필요합니다. 그림 4와 같이 Snowflake 키 계층은 1) 루트 키, 2) 계정 키, 3) 테이블 키 및 4) 파일 키와 같이 네 가지 수준으로 구성됩니다. (부모) 키의 개별 계층은 암호화, 즉, 하위의 (자식)키 계층을 포함합니다. 개발 계정 키는 하나의 사용자 키에 매핑되며, 개별 테이블 키는 하나의 데이터베이스 테이블과 연관되어 있고, 개별 파일 키는 하나의 테이블 키에 매핑되어 있습니다. 계층화된 키 모델은 개별 키가 연관되어 있는 데이터 양을 제한하기 때문에 보안에서는 좋은 사례입니다. 그림 4의 박스에 표시된 것과 같이 각 계층은 하위에 존재하는 키의 범위를 구조화하여 관리합니다. Snowflake의 계층적 키 모델은 개별 사용자 계정에 별도의 계정 키가 존재하기 때문에, 멀티-테넌트 아키텍처에서 사용자 데이터 격리를 보장하는데 활용될 수 있습니다.
3.5.2 Key Life Cycle
앞서 설명한 개별 암호화 키가 관여하는 데이터의 양을 제한하는 것과 마찬가지로 Snowflake는 암호화 키를 사용할 수 있는 기간도 제한하고 있습니다. 암호화 키는 1) 사전 작업 생성 단계, 2) 키를 사용하여 암호화(발신자 사용 기간) 및 암호 해독(수신자 사용 기간)에 사용되는 운영 단계, 3) 암호화 키를 더 이상 사용하지 않는 사후 작업 단계 및 4) 암호화 키를 폐기하는 4단계를 통해 처리됩니다. 암호화 키가 더 이상 필요한 데이터를 암호화하지 않는 경우에만 암호화 키는 단계 3 또는 4로 이동됩니다. Snowflake는 키 교체를 사용된 originator-usage period와 recipient-usage period를 사용하여 키 사용 기간을 제한합니다.
- Key rotation : 키 교체는 일정한 주기(예: 한달에 한번)마다 새 버전의 암호화 키를 생성합니다. 키 교체 주기 후, 새 버전의 키가 생성되고, 이전 버전 키는 "retired"상태가 됩니다. 폐기된 버전은 데이터를 복호화하는 용도로만 사용할 수 있습니다. 키 계층에서 새로운 자식(child) 키를 생성하거나 테이블에 새로운 데이터를 쓰는 경우에는 활성화된 버전의 암호화 키를 사용해서 데이터를 암호화합니다.
- Rekeying : Rekeying(암호화 키 갱신)은 새로운 암호화 키를 사용하여 이전 데이터를 다시 암호화하는 프로세스입니다. 특정 시간 주기(interval)이 지나면, 폐기 키(retired key)로 암호화된 데이터는 활성화 키를 사용하여 다시 암호화됩니다. Rekeying은 키 교체 작업과 독립된 특성이 있습니다. 즉, 키 교체는 암호화 키가 활성화 상태(발신자 사용)에서 retired 상태(수신자 사용)로 변경하는 것을 의미하며, 암호화 키 갱신은 retired 상태의 키를 안전 폐기하는 것을 의미합니다.
그림 5는 단일 테이블 키의 수명 주기를 설명하고 있습니다. 암호화 키가 한달에 한번 교체된다고 가정하겠습니다. 테이블 파일 1과 2는 key1의 버전1(k1v1)을 사용하여 2014년 4월에 생성되었고, 2014년 5월에 해당 키가 버전2(k1v2)로 교체되었고, k1v2를 사용하여 테이블 파일 3이 생성되었습니다. 2014년 6월에는 key1이 버전 3(k1v3)로 교체되었고 두 개의 파일이 해당 키를 사용하여 생성되었습니다. 2014년 6월 이후에는 해당 테이블에 대한 데이터 변경 작업이 수행되지 않았습니다. 2015년 4월에 k1v1은 1년이 경과하여 폐기처리 되어야 합니다. 새로운 키인 key2 버전1(k2v1)이 생성되고, k1v1과 연관된 모든 파일들은 k2v1를 사용하여 키 재배정 과정을 수행합니다. 2015년 5월에는 k1v2에 동일한 작업이 수행되어 k2v2를 사용하여 테이블 3의 키가 재배정되었습니다. 2015년 6월에 테이블 파일 4와 5가 k2v3를 사용하여 생성되었습니다. 계정 키와 테이블 키 그리고 루트 키와 계정 키 간에는 유사한 체계로 구현되었습니다. 키 계층의 개별 단계는 루트 키를 포함하여 키 교체와 키 갱신과 관련된 암호화 키 관리 체계를 따릅니다. 계정 및 루트 키의 교체 및 갱신 작업에는 하위 수준의 키만 신규 키로 암호화하기 때문에 별도의 데이터 파일을 다시 암호화할 필요가 없습니다. 그러나 테이블과 파일 키는 다른 방식으로 동작합니다. 파일 키는 테이블 키와 연관되어 있지 않습니다. 대신 파일 키는 테이블 키와 파일 이름의 조합으로 암호화를 진행합니다. 즉, 테이블 키가 변경될 때마다 관련된 모든 파일 키가 변경됨으로 영향을 받은 테이블의 파일들은 재암호화 과정이 필요합니다. 그러나, 이 방식의 가장 큰 이점은 개별 파일 키를 생성, 관리 및 전달할 필요가 없다는 것입니다. 수십억 개의 파일을 처리해야 하는 Snowflake와 같은 시스템에서는 이와 같은 방식을 지원하지 않는다면 수십 기가 바이트의 파일 키를 관리 및 처리해야 합니다. 또한, Snowflake의 스토리지와 컴퓨팅 분리를 통해 사용자 워크로드에 영향을 주지 않고 재암호화 과정을 수행할 수 있기 때문에 우리는 이와 같은 암호화 기능을 설계하였습니다. 즉, 암호화 키 갱신은 사용자 워크로드를 수행하지 않는 다른 Worker node에서 백그라운드 작업으로 수행됩니다. 파일의 암호화 키가 다시 배정된 후, Snowflake는 새로운 암호화된 파일을 참조하도록 데이터베이스 테이블의 메타정보를 트랜잭션 기반으로 갱신합니다. 현재 Worker node에서 처리 중인 모든 사용자 쿼리가 완료되면 이전 파일은 삭제 처리됩니다.
3.5.3 End-to-End Security
Snowflake는 암호화 키의 계층의 루트 키 생성, 저장 및 사용을 위한 변조 방지와 매우 안전한 방식을 위해 AWS CloudHSM을 사용합니다. AWS CloudHSM은 AWS의 VPC와 통합된 하드웨어 기반의 보안 모듈입니다. 루트키는 HSM 장치 이외의 다른 곳에서 사용될 수 없습니다. 즉, 루트키를 사용하는 모든 암호화 작업은 HSM 내에서만 실행됩니다. 따라서, HSM 장치에 대한 허가된 접근 권한 없이 하위 수준 키를 해체하여 사용할 수 없습니다. 또한, HSM은 계정 및 테이블 수준의 키를 생성하는 데도 사용됩니다. 서비스 중단 가능성을 최소화하기 위해 AWS CloudHSM을 고가용성이 보장되도록 구성하였습니다. 데이터 암호화 외에도 Snowflake는 다음과 같은 방식으로 사용자 데이터를 보호하고 있습니다:
1. S3에 대한 접근 정책을 통한 스토리지 격리.
2. 데이터베이스 객체에 대한 세분화된 접근 제어를 위한 사용자 계정 내 역할 기반 접근 제어.
3. 클라우드 공급자(Amazon)가 데이터를 참조하지 않기 위한, 암호화된 데이터 가져오기 및 내보내기.
4. 보안 접근 제어를 위한 Two-factor 및 페더레이션(타사) 인증.
요약하면 Snowflake는 AWS CloudHSM에 기반을 둔 계층적 키 모델을 제공하고, 암호화 키 교체작업을 표준화된 수명 주기를 준수합니다. 암호화 키 관리는 사용자에게 완벽하게 투명하며 구성, 관리 및 다운타임이 필요로 하지 않습니다. 이는 완벽하게 end-to-end 암호화 및 보안을 가능하게 하는 포괄적인 보안 전략의 일부입니다.
마치며...
Snowflake가 2012년에 설립되었을 때 데이터베이스 영역에서는 단기간 내에 12개 이상의 새로운 솔루션들이 등장하였으며, 대다수 Hadoop 기반의 SQL 처리 모델을 채택하였습니다. 그 당시에는 클라우드를 위한 "클래식" 데이터 웨어하우스 시스템을 완전히 새로운 기술로 설계하고 구축하는 것은 위험한 도전으로 간주되었습니다. 3년의 개발 끝에 우리는 우리의 선택이 옳았다는 것을 확신했습니다. 지난 시간 동안 Hadoop은 RDBMS를 대체하지 못햇으며, 단순하게 RDBMS의 단점을 보완하는 데 그쳤습니다. 사람들은 여전히 관계형 데이터베이스를 원했지만, 동시에 더 효율적이고 유연하며 클라우드에 더 적합한 데이터베이스를 원하고 있습니다. Snowflake는 이와 같은 시장의 요구 사항을 충족하기 위해서 클라우드 환경에 구축하였고, 사용자가 원하는 RDBMS의 기능을 충족시켰습니다. 다중 클러스터 공유 데이터 아키텍처의 탄력성은 사용자가 데이터 처리 하는 작업의 방식을 변화시켰습니다. SaaS 모델은 사용자가 시스템을 쉽게 테스트해보고 사용할 수 있게 했을 뿐만 아니라 개발 및 테스트에 큰 도움이 되었습니다. 단일 프로덕션 버전과 온라인 업그레이드를 통해 기존 개발 모델에서 할 수 있는 것보다 훨씬 빠르게 새로운 기능을 출시하고 개선 사항을 제공하며 문제를 해결할 수 있게 되었습니다. 우리는 반정형 데이터 활용이 유용할 것이라고 기대했지만 실제 고객 환경에서 채택 속도에 기대 이상이었습니다. 우리는 대다수의 기업 환경에서 JSON과 같은 반정형 데이터를 저장하고 RDBMS에 로드할 수 있는 형식으로 변환하는 두 가지 용도로 Hadoop을 사용하고 있다는 사실을 발견했으며, Snowflake는 반정형 데이터를 클라우드 스토리지에 저장하고 SQL 인터페이스로 반정형 데이터를 처리할 수 있는 기능을 제공함으로써, 기존 데이터베이스 시스템뿐만 아니라 Hadoop 클러스터도 Snowflake로 대체할 수 있다는 사실을 알게 되었습니다. 물론 굉장히 어렵고 고통스러운 작업이었습니다. 이제 Snowflake는 사용자가 원하는(그리고 지불할 용의가 있는) 성능이라는 하나의 조정 매개변수만 남아 있습니다. Snowflake의 성능은 특히 튜닝하지 않는 측면을 고려할 때 이미 매우 경쟁력이 있지만 솔루션을 구현하는데 부족한 시간 때문에 적용하지 못했던 다양한 최적화 방식이 남아 있었습니다. 제품 출시 후 다소 예상치 못한 일이지만, 핵심 성능은 거의 대부분의 사용자에게 문제가 되지 않는 것을 파악했습니다. 그 이유는 가상 웨어하우스에서 제공하는 탄력적 컴퓨팅이 때때로 필요한 성능 향상을 제공할 수 있기 때문입니다. 그래서 우리는 시스템의 다른 측면에 개발 노력을 집중할 수 있었습니다. 우리가 직면한 가장 큰 기술적 과제는 시스템의 SaaS 및 멀티-테넌시 측면과 관련이 있습니다. 수백 명의 사용자를 동시에 지원할 수 있는 메타데이터 계층을 구축하는 것은 매우 어렵고 복잡한 작업이었습니다. 다양한 유형의 노드 장애, 네트워크 장애 및 지원 서비스를 처리하는 것은 끝없는 싸움이었습니다. 보안은 외부 공격, 사용자 자신, 내부 사용자로부터 시스템과 사용자 데이터를 보호하는 큰 주제였으며 앞으로도 그럴 것입니다. 매일 수백만 개의 쿼리를 실행하는 수백 개의 노드로 구성된 라이브 시스템을 유지하면서 많은 만족을 얻으려면 개발, 운영 및 지원에 대한 고도로 통합된 접근 방식이 필요했습니다. 오늘날 Snowflake 사용자들은 시스템 진보에 영향을 미치는 점점 더 큰 양의 데이터를 기반으로 더 복잡한 워크로드를 Snowflake 시스템에서 사용하고 있습니다. 우리는 현재 사용자 상호 작업을 최소화하는 방향으로 추가적인 메타정보 구조와 데이터 재구성 작업을 제공하여 데이터 접근 성능을 개선하는 작업을 수행중에 있습니다. 또한, 우리는 표준 SQL과 반정형 데이터 처리에 대한 핵심 쿼리 처리 기능을 지속해서 개선하고 있습니다. 이를 통해, 워크로드 규모가 증가하더라도 지속적인 성능 개선을 위해 데이터 스큐 처리 및 부하 분산 전략을 지속적으로 개선할 예정에 있습니다. 궁극적으로는 시스템을 더욱 탄력적으로 함으로써, 사용자에게 워크로드 관리를 단순화하는 솔루션을 제공하는 것을 목표로 하고 있습니다. 또한, 실시간 대용량 데이터 수집과 같은 문제를 포함하여 기존 시스템과의 통합을 위해 3rd 관계사와 지속해서 노력하고 있습니다. Snowflake의 가장 큰 미래 과제는 완전한 셀프-서비스 모델로의 전환입니다. 이는 사용자가 어떤 단계에서도 당사 개입 없이 시스템에 계정을 생성하고, 시스템을 사용할 수 있는 것입니다.
'Snowflake - The Data Cloud' 카테고리의 다른 글
Snowflake Data Cloud (0) | 2021.12.08 |
---|---|
Cloud Data Platforms (0) | 2021.12.08 |
Cloud Data Lakes (0) | 2021.12.07 |
Snowflake – Partitioning (0) | 2021.11.30 |
Snowflake의 데이터 공유(Data Sharing) (0) | 2021.11.20 |