- 개요
- 1. Apache Iceberg에서 초고속 분석 쿼리 아키텍처 구축
- 1.1. Apache Iceberg의 성공과 한계
- 1.2. Apache Iceberg 성능 최적화의 세 가지 핵심 요소
- 1.3. Iceberg 테이블 최적화 방법
- 2. 저지연, 고동시성 워크로드를 위한 엔진 설계
- 2.1. 기존 데이터 레이크 엔진이 느린 이유
- 2.2. Apache Iceberg 쿼리 수명 주기의 네 단계
- 3. Apache Iceberg의 실시간 업데이트 한계와 해결책
- 3.1. Apache Iceberg의 실시간 업데이트 한계
- 3.2. 실시간 업데이트를 위한 아키텍처 패턴: Iceberg 옆에 실시간 레이어 두기
- 4. Phoenix AI의 Iceberg 최적화 전략
- 4.1. Phoenix AI의 Iceberg 최적화 기능
- 4.2. Phoenix AI 벤치마크 및 가속화 방법
- 5. 실시간 분석 시스템 설계 시 고려사항
- 5.1. 종단 간(End-to-End) 지연 시간의 세 가지 주요 레이어
- 5.2. 실시간 레이어에 포함할 테이블 선택
- 5.3. 건강한 Iceberg 테이블의 의미
- 5.4. 조인(Joins)의 중요성과 동시성 문제 해결
- 6. 실제 사례 및 Q&A
- 6.1. 실제 산업 사례
- 6.2. Q&A: 실시간 레이어와 Iceberg 간의 데이터 계층화
- 7. Phoenix AI와 StarRocks 관련 Q&A
- 7.1. Phoenix AI와 StarRocks의 관계
- 7.2. Phoenix AI의 기술적 특징 및 지원
- 8. Apache Spark 스트리밍 및 Iceberg 로드맵 Q&A
- 8.1. Apache Spark 스트리밍 환경에서의 최적화
- 8.2. Apache Iceberg 로드맵에 대한 생각
개요
Apache Iceberg에서 초고속 분석 서빙을 구현하는 방법은? 테이블 관리, 엔진 선택, 그리고 실시간 업데이트를 위한 별도의 레이어라는 세 가지 핵심 요소를 최적화해야 합니다. 특히 Iceberg 자체의 실시간 업데이트 한계로 인해 별도의 실시간 레이어를 두는 것이 중요합니다.
1. Apache Iceberg에서 초고속 분석 쿼리 아키텍처 구축
Apache Iceberg에서 초고속 분석 쿼리를 구현하려면 테이블 관리, 엔진 선택, 그리고 실시간 업데이트를 위한 별도의 레이어라는 세 가지 핵심 요소를 최적화해야 한다.
1.1. Apache Iceberg의 성공과 한계
- Apache Iceberg는 데이터 저장 형식의 표준으로 자리 잡았다.
- 많은 팀이 Apache Iceberg를 선택하며, 이는 데이터 소유권을 보장하는 개방형 형식이기 때문이다.
- 독점 형식은 특정 벤더에 종속되어 데이터 이동이 어렵지만, Iceberg는 모든 엔진이 데이터를 읽을 수 있어 이러한 문제를 해결한다.
- 하지만 Apache Iceberg는 실시간 분석에서 느리다는 인식이 있다.
- 많은 팀이 실시간 OLAP(온라인 분석 처리) 저장소나 고객 대면 애플리케이션을 위해 Iceberg에서 데이터를 내보내 별도의 복사본을 만든다.
- 이는 Apache Iceberg가 느리다는 가정 때문이거나, 실제 사용 사례에서 느렸던 경험 때문이다.
- Iceberg가 느리다는 인식은 오해일 수 있다.
- 지난 3년간 "객체 스토리지는 느리다", "데이터 레이크는 배치 처리 전용이다", "실시간 성능은 독점 솔루션이 필요하다"는 인식이 있었다.
- 그러나 최신 실시간 분석 데이터베이스(예: Starburst, Enterprise ClickHouse)는 S3와 같은 객체 스토리지에 데이터를 저장하는 공유 데이터 아키텍처를 사용하며, 낮은 지연 시간과 높은 동시성 성능을 제공한다.
1.2. Apache Iceberg 성능 최적화의 세 가지 핵심 요소
- 테이블 관리: Iceberg 테이블을 최적화해야 한다.
- Apache Iceberg는 데이터 웨어하우스 기능이 많지만, 데이터베이스처럼 테이블 유지 관리 작업을 자동으로 처리하지 않는다.
- 따라서 파일 크기 최적화를 위한 컴팩션과 같은 작업을 직접 수행해야 한다.
- 엔진 선택: 저지연, 고동시성 워크로드에 최적화된 엔진을 선택해야 한다.
- 서빙을 위한 엔진을 선택할 때 특정 아키텍처 선택과 기능을 고려해야 한다.
- 형식 자체: Apache Iceberg 메타데이터 읽기 비용을 줄여야 한다.
- Apache Iceberg 메타데이터는 어떤 엔진에서든 읽기 비용이 매우 높다.
- 특히 업데이트 및 삭제가 있는 실시간 데이터의 경우, Apache Iceberg는 이러한 요구 사항을 충족하기 어렵다.
1.3. Iceberg 테이블 최적화 방법
- 테이블 레이아웃을 최적화해야 한다.
- 데이터 웨어하우징의 모범 사례를 유지해야 한다.
- 프레디케이트(조건)에 맞춰 파티션을 나누고, 필터링할 열을 기준으로 데이터를 정렬해야 한다.
- 데이터 파일 크기를 0.5GB에서 1GB로 유지하도록 컴팩션을 수행해야 한다.
- 삭제 파일이 있는 경우, 성능 향상을 위해 마이너 컴팩션을 실행하여 삭제 파일을 압축해야 한다.
- 테이블 메타데이터와 데이터 파일을 깨끗하게 유지해야 한다.
- Apache Iceberg는 테이블 형식이므로, 테이블 유지 관리 작업을 자동으로 수행하지 않는다.
- 따라서 Spark나 엔진 자체를 사용하여 테이블 메타데이터와 데이터 파일을 정리해야 한다.
- 스냅샷을 주기적으로 만료시켜야 한다.
- 너무 많은 만료되지 않은 스냅샷은 쿼리 계획을 느리게 하고 스토리지 사용량을 증가시킨다.
- 메타데이터 파일을 다시 작성하고, 고아 파일(orphan files)을 제거해야 한다.
- 쓰기 모드와 통계를 활용해야 한다.
- Copy-on-write (CoW) 테이블은 읽기에 최적화되어 가장 빠른 서빙을 제공하지만, 파일 전체를 다시 쓰므로 쓰기 비용이 높고 실시간 업데이트에는 적합하지 않다.
- Merge-on-read (MoR) 테이블은 쓰기 비용이 저렴하지만, 읽기 시 삭제 파일을 더 많이 필터링해야 하므로 읽기 비용이 높다.
- Iceberg v2의 삭제 벡터(deletion vectors)는 이러한 읽기 비용을 줄이는 데 도움이 된다.
- 테이블 통계를 항상 최신 상태로 유지해야 한다.
- 통계가 없으면 엔진이 쿼리 계획을 정확하게 세울 수 없어 성능이 크게 저하될 수 있다.
- 건강한 테이블은 필수적이다.
2. 저지연, 고동시성 워크로드를 위한 엔진 설계
Apache Iceberg에서 저지연, 고동시성 워크로드를 처리하려면 엔진이 메타데이터 처리, 쿼리 계획, 데이터 스캔, 실행 방식 등 네 가지 핵심 단계에서 최적화되어야 한다.
2.1. 기존 데이터 레이크 엔진이 느린 이유
- 기존 엔진은 내부 분석 워크로드에 맞춰 설계되었다.
- 고객 대면 애플리케이션에는 거의 사용되지 않았다.
- 수십 개의 동시 쿼리와 몇 분의 쿼리 지연 시간은 허용 가능한 수준이었다.
- 다양한 스토리지에 대한 인플레이스(in-place) 분석에 최적화되어 있다.
- 단일 스토리지 최적화보다는 여러 스토리지(예: 트랜잭션 데이터베이스)에서 분석을 수행하는 데 중점을 둔다.
- 높은 가용성(High Availability)이 중요하지 않았다.
- 대부분 내부용이므로 SLA(서비스 수준 계약)나 고가용성은 큰 문제가 아니었다.
- 고객 대면 워크로드는 수익과 직결되므로 중요하지만, 내부 테스트 클러스터는 30분 정도 다운되어도 문제가 되지 않았다.
- 단일 코디네이터는 고가용성 문제를 일으킬 수 있다.
- 배치 분석에 최적화되어 있다.
- 쿼리 계획이 복잡하고, 데이터 셔플링 단계마다 중간 결과를 디스크에 저장한다.
- 이는 5시간짜리 작업이 중간에 중단되어도 재개할 수 있도록 하기 위함이다.
- 반면, 서빙은 훨씬 높은 동시성과 안정적인 P99 쿼리 지연 시간을 요구한다.
- 사기 탐지나 고객 대면 사용 사례처럼 대규모 동시성과 안정적인 성능이 필요하다.
- Apache Iceberg에 모든 데이터가 통합되므로, 다른 스토리지 형식에 대한 최적화보다는 Iceberg 자체에 대한 최적화가 필요하다.
- Iceberg는 자체적인 읽기 비용이 발생한다.
- Iceberg의 메타데이터 체인 구조는 파일 위치를 찾는 데 좋지만, 읽기에는 어렵다.
- 객체 스토리지에서 단일 읽기는 약 100밀리초가 소요되며, 엔진의 왕복 시간도 약 100밀리초이다.
- 통계 관리, 삭제 파일 처리 등 Iceberg 서빙 레이어를 구축할 때 고려해야 할 사항이 많다.
2.2. Apache Iceberg 쿼리 수명 주기의 네 단계
- 메타데이터 해결 (Resolve Metadata)
- 카탈로그에서 S3에 저장된 메타데이터 위치를 파악하고, 메타데이터를 해결하여 읽을 데이터 파일을 찾는다.
- Avro 파일로 된 메타데이터 레이어는 읽기 비용이 매우 높다.
- Avro 파일은 행 지향적이며, 압축 해제 및 역직렬화에 많은 비용이 든다.
- 8MB 파일을 처리하는 데 코어당 약 1초가 소요된다.
- 행 지향적 특성 때문에 코디네이터에서 단일 스레드로 처리되어, 매 쿼리마다 너무 많은 매니페스트 파일이 있으면 매우 비효율적이다.
- 엔진은 메타데이터 레이어에 대한 특정 최적화 작업을 수행해야 한다.
- 예를 들어, Avro 파일을 플래너 노드뿐만 아니라 컴퓨팅 노드에서 병렬로 읽는 방법이 필요하다.
- 메타데이터 캐싱 시 Avro 파일 자체보다는 역직렬화된 객체를 캐싱해야 한다.
- 계획 (Planning)
- 올바른 읽기 순서를 결정하여 어떤 데이터를 읽을지 계획한다.
- 비용 기반 최적화 프로그램(Cost-Based Optimizer)을 선택해야 한다.
- 규칙 기반 최적화 프로그램은 단순한 집계 외에는 작동하지 않는다.
- 쿼리에 조인이 포함된 경우, 최적화 프로그램은 조인 성능에 가장 중요한 요소이다.
- 계획이 잘못되면 성능에 엄청난 차이가 발생한다.
- 스캔 (Scanning)
- 객체 스토리지에 접근하는 횟수를 최소화하여 가능한 한 적은 양의 데이터를 스캔한다.
- 캐싱을 최대한 활용해야 한다.
- S3와 같은 객체 스토리지는 저렴하고 확장 가능하지만 빠르지 않다.
- Iceberg에서 가져온 데이터와 메타데이터를 모두 캐싱해야 한다.
- 캐싱 프레임워크는 엔진과 통합되어 네트워크 비용을 줄여야 한다.
- 데이터 스캔량을 줄여야 한다.
- 파티션, 파일, 행 그룹, 페이지 수준에서 가지치기(pruning)를 수행하여 필터를 최대한 많이 푸시다운(pushdown)해야 한다.
- 지연 구체화(late materialization)를 통해 모든 열 필터가 적용된 후에야 열을 행으로 변환해야 한다.
- 런타임 필터(runtime filters)를 사용하여 처리할 데이터 양을 줄여야 한다.
- 삭제 파일 병합을 위해 Iceberg 삭제 작업에 최적화된 엔진이 필요하다.
- 실행 (Execution)
- 모든 작업을 병렬로 실행하고 스레드 전환을 최소화한다.
- 파이프라인 실행(pipeline execution)에 최적화된 엔진을 찾아야 한다.
- 작업을 작은 파이프라인으로 분해하여 컨텍스트 전환과 스레드 전환을 줄인다.
- 쿼리당 오버헤드가 낮아지고, 동시성이 증가해도 지연 시간이 유지된다.
- 벡터화된 CPU 최적화 연산자(vectorized CPU-optimized operators)를 사용해야 한다.
- SIMD(Single Instruction, Multiple Data) 명령 세트를 활용하여 인메모리에서 데이터를 배치로 처리한다.
- OLAP 시스템과 분석 쿼리는 항상 열 단위로 처리되므로, 배치 처리가 많을수록 속도가 빨라진다.
- Rust나 C++와 같은 저수준 언어로 작성된 엔진이 SIMD를 최대한 활용할 수 있다.
3. Apache Iceberg의 실시간 업데이트 한계와 해결책
Apache Iceberg는 실시간 업데이트에 취약하며, 이를 해결하기 위해 별도의 실시간 레이어를 두는 것이 가장 효과적인 방법이다.
3.1. Apache Iceberg의 실시간 업데이트 한계
- Apache Iceberg는 실시간 업데이트에 어려움을 겪는다.
- Iceberg에 매우 자주 쓰기 작업을 수행하면 많은 문제가 발생한다.
- 모든 쓰기 커밋은 새로운 스냅샷을 생성하며, 5분마다 쓰면 하루에 288개의 스냅샷이 생성된다.
- 여러 작성자가 동시에 작업하면 작은 파일이 쌓여 컴팩션이 항상 문제가 된다.
- 특히 최근 쓰기 작업에 대한 컴팩션은 엔진에 매우 어렵다.
- Copy-on-write와 Merge-on-read 모두 실시간 업데이트에 완벽한 해결책이 아니다.
- Copy-on-write (CoW)는 파일 전체를 다시 쓰므로 구현은 쉽지만, 실시간이 아니다.
- Merge-on-read (MoR)는 많은 삭제 파일을 생성하며, 이 삭제 파일은 일반적으로 마이너 컴팩션을 통해 병합해야 한다.
- 그러나 이러한 컴팩션은 실시간 업데이트 속도를 따라가지 못한다.
- MoR 테이블을 1~2분 미만으로 구성하면 쿼리 성능에 심각한 영향을 미치고, 엔진이 수행할 수 있는 모든 프레디케이트 푸시다운을 차단한다.
- 따라서 Apache Iceberg는 가까운 미래에도 실시간 업데이트에 어려움을 겪을 것으로 예상된다.
3.2. 실시간 업데이트를 위한 아키텍처 패턴: Iceberg 옆에 실시간 레이어 두기
- Apache Iceberg 옆에 별도의 실시간 레이어를 두는 것이 효과적이다.
- 가장 최신 데이터는 실시간 레이어로 들어간다.
- 이중 쓰기(dual writes)를 통해 Apache Iceberg와 실시간 레이어에 동시에 데이터를 쓰거나, 실시간 레이어에서 Apache Iceberg로 비동기 동기화 프로세스를 구축할 수 있다.
- 이 실시간 레이어는 변경 가능한 초 단위의 데이터 업데이트를 처리할 수 있어야 한다.
4. Phoenix AI의 Iceberg 최적화 전략
Phoenix AI는 StarRocks 기반의 분석 데이터베이스 및 서빙 레이어로, Iceberg의 메타데이터, 계획, 스캔, 실행 문제를 해결하고 실시간 업데이트를 위한 자체 테이블 형식을 제공하여 초고속 성능을 달성한다.
4.1. Phoenix AI의 Iceberg 최적화 기능
- 메타데이터 문제 해결을 위한 Iceberg 전용 최적화.
- 병렬 매니페스트 파싱: 수백 개의 컴퓨팅 노드를 사용하여 매니페스트 파일을 병렬로 파싱하여 Iceberg 메타데이터 파일 읽기를 수평 확장 가능한 프로세스로 만든다.
- 캐시된 Avro 객체: 메타데이터 파일 자체를 캐싱하는 대신, Avro 파일의 역직렬화된 객체를 캐싱한다.
- 테이블 크기에 따라 자동으로 최적의 경로를 선택한다.
- 고급 쿼리 계획 기능.
- 지난 4~5년간 최적화된 비용 기반 최적화 프로그램을 사용한다.
- 외부 테이블을 포함한 통계를 수집하여 데이터 웨어하우징의 저지연 트릭을 Iceberg에 적용한다.
- 효율적인 스캔을 위한 캐싱.
- 메모리와 NVMe SSD에 메타데이터 및 데이터 캐시를 모두 제공한다.
- 객체 스토리지로의 이동을 최소화하여 쿼리를 실시간으로 만든다.
- 최적화된 실행.
- C++로 작성된 벡터화된 SIMD 연산자를 사용하여 모든 컴퓨팅 노드가 SIMD 명령 세트를 활용하고 배치를 처리한다.
- 이는 현재 OLAP 엔진에서 얻을 수 있는 최고의 성능을 제공한다.
- 실시간 업데이트를 위한 기본 키 테이블.
- Phoenix AI는 자체 기본 키 테이블 형식을 제공하여, 업데이트 및 삭제가 있는 데이터에 대해 10초 미만의 데이터 신선도를 달성한다.
- 이 형식은 Iceberg 테이블 형식과 함께 사용되며, 거의 동일한 성능으로 쿼리할 수 있다.
4.2. Phoenix AI 벤치마크 및 가속화 방법
- Phoenix AI는 Iceberg 테이블에서 뛰어난 성능을 보인다.
- Iceberg Trino, Databricks Delta와 비교했을 때, Phoenix AI는 Iceberg 테이블에서 내부 테이블과 5%밖에 차이 나지 않는 성능을 보여준다.
- 이는 모든 데이터를 Iceberg에 단일 진실 공급원(single source of truth)으로 유지하면서도 높은 성능을 얻을 수 있음을 의미한다.
- Phoenix AI는 Iceberg 쿼리를 가속화하는 다양한 방법을 제공한다.
- Iceberg 테이블을 직접 쿼리: Phoenix AI는 건강한 Iceberg 테이블에서 대부분의 워크로드를 처리할 수 있다.
- 비동기 구체화된 뷰(asynchronous materialized views)를 통한 가속화: 테이블 유지 관리가 어렵거나 특수 보조 인덱스가 필요한 경우, Iceberg 테이블을 Phoenix AI의 기본 형식으로 구체화할 수 있다.
- 이는 형식을 Phoenix AI의 기본 형식으로 변환하여 변환 작업을 다시 할 필요가 없게 한다.
- Iceberg 기본 테이블의 변경 사항이 Phoenix AI에 자동으로 동기화되어 논리적으로 단일 진실 공급원을 유지한다.
- 투명한 쿼리 재작성(transparent query rewrite)을 통해 쿼리는 Iceberg 테이블을 가리키지만, 가장 적합한 구체화된 뷰로 자동 라우팅된다.
- 구체화된 뷰는 복잡한 워크로드에 유용하다.
- Apache Spark와 같은 다른 도구를 사용하는 대신, 구체화된 뷰를 사용하여 사전 집계(pre-aggregation) 및 비정규화(denormalization)를 지원한다.
- 쿼리 재작성을 지원하므로, 쿼리를 변경하지 않고도 성능 향상을 얻을 수 있다.
- Phoenix AI의 실시간 레이어는 기본 키 테이블을 사용한다.
- Apache Iceberg는 병합 작업이 비싸고 프레디케이트 푸시다운을 방해하여 실시간 모드에서 작동하기 어렵다.
- Phoenix AI의 기본 키 테이블은 병합을 나중에 하는 대신, 쓰기 시점에 인덱스를 구축하여 데이터 위치를 직접 파악하고 삭제로 표시한다.
- 이로 인해 읽기 시 병합 작업이 필요 없어 쿼리 성능에 영향을 주지 않으며, 변경 가능한 데이터에 대해 초 단위의 데이터 신선도를 제공한다.
5. 실시간 분석 시스템 설계 시 고려사항
실시간 분석 시스템을 설계할 때는 데이터 수집부터 쿼리 실행까지 전체 지연 시간을 고려하고, 모든 테이블을 실시간 레이어에 둘 필요는 없으며, 조인과 동시성 문제를 해결하기 위한 전략이 필요하다.
5.1. 종단 간(End-to-End) 지연 시간의 세 가지 주요 레이어
- 데이터 수집(Ingestion)은 상당한 지연 시간을 유발한다.
- Spark나 Flink와 같은 스트림 처리 엔진을 사용하더라도 Kafka에서 데이터 레이크로 데이터를 매초 플러시하기는 어렵다.
- 객체 스토리지의 특성상, 데이터를 너무 빨리 플러시하면 스토리지 시스템에 과부하가 걸리고 읽기 성능에 큰 부담을 준다.
- 실제로는 5분이 가장 일반적인 커밋 간격이며, 1분마다 플러시하는 것도 흔치 않다.
- 데이터 변환(Transformation)은 종종 간과되는 단계이다.
- 강력한 엔진이 있다고 해서 모든 데이터를 엔진에 넣고 바로 초 단위 성능을 기대할 수는 없다.
- 데이터 모델링과 변환이 누락되면 쿼리 지연 시간이 증가하고 쿼리가 대기열에 쌓일 수 있다.
- MPP(Massively Parallel Processing) 엔진은 즉각적인 쿼리 실행을 제공한다.
- MPP는 항상 켜져 있고 준비된 많은 컴퓨팅 성능을 제공한다.
- 쿼리는 재시도를 위해 계획되지 않으며, 즉각적인 실행을 위해 10밀리초 이내에 계획된다.
- 이는 워밍업에 몇 초가 필요한 다른 컴퓨팅 엔진과 큰 차이가 있다.
5.2. 실시간 레이어에 포함할 테이블 선택
- 모든 테이블을 실시간 레이어에 둘 필요는 없다.
- 일반적으로 매우 인기 있고 변경 가능한 테이블의 약 10%만 실시간 레이어에 두면 된다.
- 변경 가능한 테이블이 전체 쿼리 지연 시간을 결정한다.
- 과거에는 Hadoop의 데이터가 대부분 추가 전용(append-only)이라고 가정했지만, 이는 빠른 분석에 적합하지 않다.
- 여러 테이블을 조인하여 분석 질문에 대한 완전한 컨텍스트를 형성할 때, 6~7개 테이블 중 하나라도 업데이트나 변경으로 인한 지연 문제가 있으면 전체 쿼리의 SLA(서비스 수준 계약) 또는 지연 시간을 결정한다.
- 예를 들어, 큰 팩트 테이블은 추가 전용일 수 있지만, 일부 차원 테이블은 자주 업데이트되어야 한다.
- 이러한 변경 사항을 제때 병합하지 못하면 데이터 신선도가 20분 또는 1시간 이상 지연될 수 있다.
- 실시간 레이어에 포함할 변경 가능한 팩트 테이블의 예시.
- 결제, 이체, 주문과 같은 테이블은 변경 가능한 팩트의 전형적인 예시이다.
- 몇 개의 열만 변경될 수 있지만, 분석 결과의 정확성을 위해 이러한 변경 사항을 실시간으로 반영하는 것이 매우 중요하다.
- 이중 수집(Dual Ingestion) 패턴을 통해 단일 진실 공급원을 유지한다.
- 차원 테이블은 전체를 실시간 레이어에 직접 넣고, 팩트 테이블은 가장 최근의 '핫' 파티션만 실시간 레이어에 둔다.
- Iceberg를 신뢰할 수 있는 단일 진실 공급원으로 유지하면서도, 성능을 위해 추가 실시간 레이어를 사용하는 것이다.
- 이는 추가 비용이 발생하지만, Iceberg 데이터 형식이 높은 처리량의 업데이트에 대한 특별한 최적화를 제공하지 않는 한 향후 2~3년간은 감수해야 할 부분이다.
5.3. 건강한 Iceberg 테이블의 의미
- 건강한 Iceberg 테이블은 세 가지를 의미한다.
- 적절하게 파티션되어야 한다.
- 정기적으로 컴팩션되어야 한다.
- 정렬되어야 한다.
- 가장 자주 사용되는 프레디케이트(조건) 또는 필터 조건과 일치하는 정렬 및 블룸 필터 인덱스를 가져야 한다.
- 테이블 설계가 부적절하면 성능에 부정적인 영향을 미친다.
- Spark나 Phoenix AI를 사용하여 Iceberg를 실시간 분석 레이어로 통합하더라도, Iceberg 테이블 자체가 제대로 설계되지 않으면 성능이 저하된다.
- 쿼리의 90번째 백분위수에서 초 단위 지연 시간을 달성하려면 테이블이 제대로 설계되어야 한다.
5.4. 조인(Joins)의 중요성과 동시성 문제 해결
- 조인은 실시간 분석 워크로드에서 필수적이다.
- 과거에는 빅데이터가 대규모 스캔과 병렬 집계에 관한 것이므로 조인이 필요 없다는 인식이 있었다.
- ClickHouse와 같은 독점 실시간 시스템도 원래는 조인을 지원하지 않았지만, 최근 12개월 동안 조인 기능을 추가하기 시작했다.
- 이는 대부분의 워크로드가 조인을 요구하기 때문이며, 특히 AI 에이전트 시대에는 전통적인 배치 지향 ETL 파이프라인을 통한 지연 시간을 감수할 수 없다.
- 데이터를 최대한 빨리 얻으려면 조인이 필요한 분석 쿼리의 비율이 0%에서 90~95%로 증가한다.
- 따라서 선택하는 분석 쿼리 엔진은 조인에 대한 강력한 지원과 저지연에 최적화되어야 한다.
- 높은 동시성 환경에서의 성능 저하 문제.
- 개발 및 테스트 환경에서 20밀리초 내에 결과를 반환하는 쿼리도, 프로덕션 환경에서 500개의 동시 쿼리가 들어오면 시스템에 과부하를 줄 수 있다.
- 각 쿼리가 상대적으로 큰 스캔과 복잡한 조인을 포함하기 때문에 시스템이 느려질 수 있다.
- 구체화된 뷰(Materialized Views)를 통한 성능 최적화.
- 자주 사용되는 고빈도 쿼리에 대해 구체화된 뷰나 파생 테이블을 생성하여 캐시와 인덱스를 효율적으로 사용하고 값비싼 테이블 스캔을 피해야 한다.
- 때로는 파티션 스캔조차도 저지연 고객 대면 분석에는 너무 비쌀 수 있다.
- 구체화된 뷰는 가볍고 관리하기 쉬운 ETL(추출, 변환, 적재) 또는 ELT(추출, 적재, 변환) 로직으로 간주할 수 있다.
- Airflow 파이프라인이나 DBT를 매 5분마다 실행하는 대신, 분석 엔진에서 구체화된 뷰를 정의하고 엔진이 기본 테이블의 새로 고침을 감지하여 데이터를 사전 조인 또는 사전 집계된 형태로 자동 변환하도록 한다.
- 쿼리 재작성을 통해 모든 분석 쿼리가 원본 테이블 대신 구체화된 뷰를 사용하게 하여 99%의 경우 초 단위 지연 시간을 제공한다.
6. 실제 사례 및 Q&A
Phoenix AI는 실제 기업에서 Apache Iceberg 기반의 레이크하우스 아키텍처를 통해 고객 대면 분석 및 AI 에이전트 워크로드에서 뛰어난 성능과 효율성을 입증했다.
6.1. 실제 산업 사례
- Demandbase 사례: ClickHouse에서 Phoenix AI로 전환.
- Demandbase는 B2B 고객 대면 분석을 위해 계정 기반 시장 진출 플랫폼을 운영하며 복잡한 비즈니스 로직을 가지고 있었다.
- 이전에는 ClickHouse를 사용했는데, 모든 데이터가 비정규화되어 스토리지 사용량이 10배 많았고, 스키마 변경 시 대량의 데이터를 이동해야 했다.
- 또한, 비정규화된 테이블이 너무 많아 49개의 클러스터를 운영해야 했다.
- Apache Iceberg를 단일 진실 공급원으로 사용하고 Phoenix AI를 그 위에 실행하여 고객 대면 분석 서빙 레이어를 직접 처리했다.
- 결과적으로 비정규화된 테이블 없이 모든 조인을 처리하고, 서빙 클러스터를 49개에서 1개로 줄였으며, 하드웨어는 60% 적게, 스토리지는 90% 적게 사용하면서도 더 나은 성능을 달성했다.
- Conductor 사례: AI 에이전트의 실시간 데이터 처리.
- Conductor는 AI 플랫폼을 운영하며 고객의 브랜드 인식을 분석하는 고객 대면 AI 에이전트 사용 사례를 가지고 있다.
- 이전에는 사전 계산된 보고서를 사용했기 때문에 데이터가 고객에게 도달하는 데 며칠이 걸렸지만, AI 에이전트와 API는 초 단위의 응답을 필요로 했다.
- 레이크하우스와 클라우드 아키텍처로 전환하여 내부 및 외부 고객 대면 분석 사용 사례를 위한 단일 레이어를 구축했다.
- 대규모 언어 모델이 언어 처리를 담당하고 Phoenix AI가 수학 및 계산을 처리하는 아키텍처를 구축했다.
- 아이디어부터 프로덕션까지 단 2개월이 걸렸고, 2억 4천만 행의 테이블을 스캔하는 쿼리가 수백 밀리초 만에 실행되었다.
- 이는 테라바이트 규모의 데이터에 대해 사전 계산 없이 실시간으로 고객 대면 AI 에이전트를 운영하는 사례이다.
6.2. Q&A: 실시간 레이어와 Iceberg 간의 데이터 계층화
- 실시간 레이어의 기본 테이블에서 Iceberg로 데이터를 계층화하는 가장 간단한 방법은 무엇인가?
- 차원 테이블: 인기 있는 차원 테이블은 계층화하지 않고 실시간 레이어에 직접 넣는다.
- 이중 수집을 통해 Iceberg 복사본은 배치 작업에 사용되며, 실시간 데이터의 중요 경로에는 포함되지 않는다.
- 팩트 테이블: 실시간 레이어에는 7일 또는 한 달과 같은 '핫' 파티션만 유지하고, Iceberg에는 전체 팩트 데이터를 유지한다.
- 쿼리 시에는 SQL을 사용하여 실시간 레이어에서 가장 최근 30일 데이터를 가져오고, Iceberg 테이블에서는 나머지 데이터를 가져와 통합한다.
- 오래된 데이터 업데이트 처리: 오래된 데이터(예: 6개월 전 데이터)가 업데이트되는 경우, 이중 수집 레이어에서 6개월보다 오래된 데이터는 실시간 레이어로 들어가지 않도록 필터를 설정한다.
- 이 데이터는 Iceberg 레이어로 계속 흘러 들어가며, 데이터를 통합할 때 이력 데이터가 나타난다.
- 이는 대부분의 변경 및 업데이트가 최근 2주 이내에 발생한다는 실용적인 가정을 기반으로 한다.
- 만약 데이터가 6개월 이상 지속적으로 업데이트된다면, 해당 데이터를 실시간 레이어에 포함하거나 테이블을 다르게 파티션하는 것을 고려해야 한다.
- 예를 들어, 가장 변경이 잦은 열 그룹을 실시간 레이어에 두고, 덜 자주 사용되고 최근에 업데이트되지 않는 열은 다른 테이블에 두어 조인을 통해 보완할 수 있다.
- 부분 업데이트(Partial Update) 기능.
- BigQuery와 StarRocks에서 볼 수 있는 부분 업데이트는 전통적인 OLTP 시스템처럼 두 개의 열만 업데이트할 수 있게 한다.
- 이는 I/O 페널티를 크게 줄이고, 데이터를 스토리지 및 캐시 레이어에 더 효율적으로 플러시하여 전체 지연 시간을 개선한다.
- 핵심은 데이터 업데이트 패턴, 즉 '데이터의 온도'를 이해하는 것이다.
- 온도가 높을수록 전문화되거나 최적화된 실시간 레이어를 고려해야 하며, 그렇지 않으면 실시간 계층에 더 적은 데이터를 넣을 수 있다.
7. Phoenix AI와 StarRocks 관련 Q&A
Phoenix AI는 StarRocks의 엔터프라이즈 에디션으로, StarRocks의 쿼리 플래너에 특정 최적화를 추가하며, Python 지원을 포함한 다양한 기능을 제공한다.
7.1. Phoenix AI와 StarRocks의 관계
- Phoenix AI는 StarRocks의 엔터프라이즈 에디션이다.
- Phoenix AI는 StarRocks 프로젝트의 원작자들이 StarRocks를 기반으로 구축한 엔터프라이즈급 Database-as-a-Service 시스템이다.
- 온프레미스 및 클라우드 배포를 모두 지원한다.
7.2. Phoenix AI의 기술적 특징 및 지원
- Phoenix AI는 StarRocks의 쿼리 플래너에 특정 최적화를 추가한다.
- Phoenix AI는 StarRocks의 쿼리 플래너에 일부 성능 최적화를 추가하지만, StarRocks의 쿼리 계획 자체를 변경하지는 않는다.
- Apache Iceberg 인덱스와 관련하여 특별한 최적화는 없다.
- Fluss을 지원한다.
- Phoenix AI는 Apache Fluss에 대한 지원이 잘 되어 있으며, 관련 문서는 이미 제공된다.
- Iceberg 통합은 외부 카탈로그 유형으로 작동한다.
- Starburst에 새로운 테이블 유형이 생성되는 것이 아니라, 외부 메타데이터 캐시 레이어로 통합된다.
- Phoenix AI는 자체 내부 카탈로그 외에 REST 기반 Apache Iceberg 카탈로그에 연결하여 메타데이터를 읽을 수 있는 외부 카탈로그 유형을 지원한다.
8. Apache Spark 스트리밍 및 Iceberg 로드맵 Q&A
Apache Spark 스트리밍 환경에서 대규모 데이터 처리 시 테이블 파티셔닝, 기본 키 설계, 쿼리 패턴 분석이 중요하며, Apache Iceberg의 로드맵은 아직 초기 단계이다.
8.1. Apache Spark 스트리밍 환경에서의 최적화
- Apache Spark 스트리밍으로 매분 5TB의 데이터를 추가 모드로 쓰는 경우.
- 테이블 파티셔닝: 테이블을 제품 유형이나 이벤트 유형과 같은 낮은 카디널리티의 범주형 열을 기준으로 5~6개의 테이블로 분할하는 것을 고려한다.
- 이는 각 테이블의 데이터 클러스터링을 개선하고, 쓰기 시간 경합을 줄이며, 동시성 및 병렬성을 향상시킨다.
- 기본 키 및 파티션 설계: 데이터의 '온도'를 고려하여 기본 키를 간결하게 설계한다.
- 자연 키 대신 해시 값이나 미리 계산된 해시 값을 기본 키로 사용하면 조회 효율성과 메모리 캐시 효율성이 크게 향상된다.
- 핫 쿼리 경로 식별: 가장 자주 사용되는 쿼리 패턴을 식별하고, 쿼리 서명이 분당 또는 시간당 몇 번 호출되는지 파악하여 워크로드에 기반한 테이블 설계를 한다.
8.2. Apache Iceberg 로드맵에 대한 생각
- Apache Iceberg의 로드맵은 아직 초기 단계이다.
- 현재까지는 채택률이 높지 않지만, 오픈 소스 커뮤니티에서 PR(Pull Request) 작업을 진행 중이며, 4.2 버전에서 통합이 이루어질 것으로 예상된다.