StarRocks 파헤치기: 고성능 OLAP 엔진의 도입부터 성능 최적화까지

이동휘·2025년 6월 14일
0

매일매일 블로그

목록 보기
28/49

컴퓨팅 성능의 발전은 데이터 처리 패러다임의 변화를 이끌고 있습니다. 전통적인 ETL(Extract, Transform, Load) 방식에서, 데이터를 먼저 적재한 후 필요에 따라 변환하는 ELT(Extract, Load, Transform) 방식으로의 전환이 가속화되고 있죠. 이러한 변화 속에서 Apache Iceberg와 같은 오픈 테이블 형식과 스키마 진화(Schema Evolution) 기술이 등장했으며, 대규모 데이터를 빠르고 유연하게 분석할 수 있는 고성능 OLAP(Online Analytical Processing) 엔진의 중요성은 그 어느 때보다 커졌습니다.

이러한 배경 속에서 최근 주목받고 있는 데이터베이스가 바로 StarRocks입니다. 이 글에서는 StarRocks가 왜 현대 데이터 아키텍처에 필요한지, 그 내부 구조는 어떻게 동작하는지, 그리고 실제 운영 환경에서 성능을 극대화하기 위한 최적화 전략은 무엇인지 깊이 있게 살펴보겠습니다.


1. 왜 새로운 OLAP 엔진이 필요한가? ELT 시대의 도래

과거 빅데이터 분석 환경에서는 모든 데이터를 하나의 거대한 테이블에 미리 가공하여 넣는 플랫 테이블(Flat Table) 구조가 일반적이었습니다. 하지만 거버넌스 환경으로의 전환이 가속화되면서, 데이터가 목적에 맞게 잘게 분리되어 유통되는 경우가 많아졌습니다. 이로 인해 여러 데이터 소스를 유연하게 JOIN하여 분석하는 능력의 중요성이 커졌습니다.

또한, 고성능 OLAP 데이터베이스를 도입하면, 데이터베이스 내에서 직접 중간 및 최종 집계 데이터를 생성(롤업)하고, 세분화된 원본 데이터를 다양하게 변환하는 작업이 가능해집니다. 이는 데이터 파이프라인의 복잡성을 줄이고, 분석 속도를 높이는 데 큰 이점을 제공합니다.

◼️ OLAP 엔진 플랫폼 비교: StarRocks vs. ClickHouse

고성능 OLAP 엔진의 대표 주자로는 StarRocks와 ClickHouse가 있습니다. 두 데이터베이스는 여러 공통점을 가지지만, 핵심적인 차이점도 존재합니다.

특징ClickHouseStarRocks
데이터 변환다양한 테이블 엔진과 Materialized View를 통해 지원 (주로 Transform-After-Load).Generated Column과 Materialized View를 통해 지원 (Generated Column을 통해 일부 Transform-Before-Load 가능).
Materialized View 업데이트원본 데이터 INSERT 시 트리거되는 실시간(Near-Realtime) 방식.사용자의 명령(수동 실행) 또는 내장 스케줄러를 통해 기본 테이블 기반으로 비동기 업데이트.
스토리지 구조LSM-Tree 기반 스토리지.LSM-Tree 기반 네이티브 스토리지 + 클라우드 분산 스토리지(S3 등) 직접 지원 (연산/스토리지 분리 가능).
JOIN 기능JOIN 기능이 상대적으로 제한적이며, 대규모 테이블 간의 복잡한 조인에는 한계가 있을 수 있음.뛰어난 JOIN 성능을 제공하여, 분리된 다양한 데이터를 유연하게 조합 가능.
데이터 거버넌스 적합성JOIN 능력의 한계로 인해, 잘게 분리된 데이터를 통합 분석해야 하는 환경에서는 부적합할 수 있음.뛰어난 JOIN 성능 덕분에, 다양한 거버넌스 환경에서 분산된 데이터를 통합 분석하는 데 매우 적합.
쿼리 엔진최적화된 MPP(Massively Parallel Processing) 아키텍처로 대규모 데이터 고속 처리 가능.최적화된 벡터화(Vectorized) 실행 엔진과 MPP 아키텍처로 대규모 데이터 고속 처리 가능.
GROUP BY 성능우수하지만, StarRocks 대비 전반적인 GROUP BY 성능은 다소 뒤처질 수 있음.테스트 전반에 걸쳐 ClickHouse 대비 우수한 GROUP BY 성능을 보임 (특히 데이터 양이 많을수록 격차 증가).

◼️ StarRocks의 주요 강점 요약

  • 고성능 JOIN: 기존 빅데이터 분석의 고질적인 문제였던 플랫 테이블 구조에서 벗어나, 정규화된 테이블들을 유연하게 조인하여 분석할 수 있습니다.
  • 고성능 단일 테이블 쿼리: 실제 분석 워크로드 기반의 벤치마크(TPC-H, SSB 등)에서 다른 OLAP 엔진 대비 뛰어난 성능을 입증했습니다.
  • 클라우드 네이티브 아키텍처: 연산(Compute)과 스토리지(Storage)를 분리할 수 있는 구조를 지원하여, 클라우드 환경에서 오토 스케일링, 비용 효율적인 운영이 가능합니다.
  • Materialized View를 통한 쿼리 가속: 스케줄러 기반의 Materialized View를 통해 데이터를 미리 집계하고 조인해 둠으로써, 복잡한 쿼리의 성능을 획기적으로 향상시킬 수 있습니다.
  • 데이터 레이크 연동 최적화: Apache Iceberg, Hudi, Delta Lake와 같은 오픈 테이블 형식과의 연동에 최적화되어 있어, 데이터 레이크에 저장된 데이터를 직접 빠르고 효율적으로 조회할 수 있습니다. (StarRocks 개발사인 CelerData는 Iceberg 커뮤니티의 주요 기여자)
  • 데이터 캐싱 메커니즘: 외부 데이터(예: 데이터 레이크)를 StarRocks 클러스터 내의 로컬 스토리지에 캐싱하여, 반복적인 쿼리 성능을 크게 향상시킬 수 있습니다.

산업계 동향: StarRocks는 WeChat, Trip.com, Tencent Games, Lenovo, Airbnb 등 다양한 글로벌 기업의 대규모 데이터 분석 플랫폼에 적용되어 그 성능과 안정성을 입증받고 있습니다. 또한, 풍부한 커넥터 생태계를 통해 다양한 데이터 소스 및 BI 도구와 손쉽게 연동할 수 있습니다.


2. StarRocks 내부 아키텍처: 어떻게 동작하는가?

StarRocks는 크게 프런트엔드(Frontend, FE)백엔드(Backend, BE/CN) 노드로 구성된 MPP(Massively Parallel Processing) 아키텍처를 가집니다.

  • 프런트엔드 (Frontend, FE): 클러스터의 두뇌
    • 역할: 메타데이터 관리, 쿼리 계획 수립 및 최적화, 스케줄링 등을 담당합니다.
    • 메타데이터 관리: 테이블 스키마, 파티션 정보, 데이터 위치 등 클러스터의 모든 메타데이터를 관리합니다.
    • 쿼리 최적화: CBO(Cost-Based Optimizer)를 사용하여 수신된 SQL 쿼리에 대한 가장 효율적인 실행 계획을 생성합니다.
    • 고가용성: 여러 FE 노드로 구성되며, 그중 하나가 리더(Leader)가 되어 메타데이터 쓰기 작업을 전담합니다. 다른 팔로워(Follower) 노드들은 Raft 프로토콜을 통해 리더의 메타데이터 업데이트를 동기화하여 고가용성을 보장합니다.
    • 주의사항: FE는 메타데이터를 메모리에 유지하므로, 클러스터 규모가 커질수록 충분한 JVM 메모리를 확보하는 것이 중요합니다. (수직적 스케일링 필요)
  • 백엔드 (Backend, BE / Compute Node, CN): 실제 데이터 처리 및 저장
    • 역할: 실제 데이터 저장 및 쿼리 실행을 담당하는 작업자 노드입니다.
    • BE (Backend Node): 네이티브 스토리지(로컬 디스크)에 데이터를 직접 저장하고, 해당 데이터에 대한 쿼리 연산을 수행합니다.
    • CN (Compute Node): 연산과 스토리지가 분리된 환경에서 연산(Compute) 역할만을 수행합니다. 데이터는 S3와 같은 외부 분산 스토리지에 저장되며, CN은 이 데이터를 읽어와 쿼리를 처리합니다.

◼️ Shared-nothing vs. Shared-data 구조

StarRocks는 배포 시나리오에 따라 두 가지 주요 아키텍처를 선택할 수 있습니다.

  • Shared-nothing 구조: 각 BE 노드가 자신만의 로컬 디스크에 데이터를 소유하고 처리하는 전통적인 MPP 구조입니다. 데이터 지역성(Data Locality)을 최대한 활용하여 높은 성능을 낼 수 있습니다.
  • Shared-data 구조 (연산/스토리지 분리): 데이터는 S3와 같은 중앙 분산 스토리지에 저장되고, CN 노드들은 이 데이터를 공유하여 연산을 수행합니다. 연산과 스토리지를 독립적으로 확장할 수 있어 유연성과 비용 효율성이 높으며, 클라우드 환경에 매우 적합합니다. 이 구조에서도 BE 노드는 외부 데이터를 로컬 디스크에 캐싱하는 데이터 캐시 역할로 활용될 수 있습니다.

🤔 꼬리 질문: Shared-nothing과 Shared-data 아키텍처는 각각 어떤 장단점을 가질까요? 어떤 비즈니스 요구사항이나 운영 환경에서 각 아키텍처가 더 유리할지 논의해 볼 수 있을까요?


3. StarRocks 내부 메커니즘: 성능의 비밀을 찾아서

StarRocks의 뛰어난 성능은 내부적으로 효율적인 스토리지 엔진과 데이터 레이아웃 설계에 기인합니다.

◼️ LSM-Tree 기반 스토리지 엔진

StarRocks는 LSM-Tree(Log-Structured Merge Tree) 기반의 스토리지 엔진을 사용합니다.

  • 동작 원리: 인입된 데이터는 먼저 메모리 내의 정렬된 버퍼(Memtable)에 기록된 후, 정렬된 상태 그대로 작은 단위의 불변 파일(SSTable, StarRocks에서는 세그먼트)로 디스크에 순차적으로 기록됩니다. 이렇게 잘게 나뉜 세그먼트들은 백그라운드에서 지속적인 병합 과정(컴팩션, Compaction)을 거쳐 더 큰 단위의 정렬된 데이터로 통합됩니다.
  • 특징: 이 구조는 랜덤 쓰기를 순차 쓰기로 변환하여 매우 높은 쓰기 성능을 제공하며, 데이터 압축에도 유리합니다.
  • 정렬 키(Sort Key)의 중요성: 데이터가 정렬 키를 기준으로 저장되므로, SELECT 쿼리의 WHERE 조건절에 정렬 키 컬럼이 포함되면 필요한 데이터 범위만 빠르게 스캔하여 성능을 크게 향상시킬 수 있습니다. (Predicate Pushdown) 따라서 자주 사용되는 필터링 조건을 고려하여 정렬 키를 신중하게 선택하는 것이 매우 중요합니다.

◼️ 정렬 키와 Prefix 인덱스

StarRocks는 정렬된 데이터에서 특정 데이터를 빠르게 찾기 위해, 일정한 간격으로 '값:위치' 형식의 稀疏索引(Sparse Index)을 생성합니다. 정렬 키는 여러 컬럼의 조합으로 생성될 수 있으며, 이 조합의 앞부분을 사용한 Prefix 인덱스로 데이터의 위치를 표현합니다.

  • Prefix 인덱스 조건:
    • 조합된 인덱스의 최대 길이는 36바이트로 제한됩니다.
    • 최대 3개의 컬럼까지만 조합에 사용될 수 있습니다.
    • CHAR, VARCHAR, STRING과 같은 문자열 타입은 한 번만, 그리고 조합의 마지막에만 사용할 수 있습니다.

◼️ 데이터 레이아웃: 파티셔닝과 버킷팅(샤딩)

StarRocks 테이블의 데이터는 파티셔닝(Partitioning)버킷팅(Bucketing, 다른 시스템의 샤딩과 유사)을 통해 여러 노드에 분산되어 저장 및 처리됩니다.

  • 파티셔닝 (Partitioning):
    • 목적: 데이터를 논리적인 단위로 분할하여 관리 효율성을 높이고, 쿼리 시 불필요한 데이터를 스캔하지 않도록 데이터 프루닝(Data Pruning)을 가능하게 합니다.
    • 설계: 주로 시간(날짜, 주, 월 등)과 같이 쿼리에서 범위 조건으로 자주 사용되는 컬럼을 파티셔닝 키로 선택합니다. LSM-Tree 구조상, 파티셔닝은 세그먼트의 정렬 경계를 명확하게 설정하는 역할을 하여, 특정 파티션에 대한 쿼리 시 다른 파티션의 데이터는 전혀 읽지 않도록 합니다.
  • 버킷팅 (Bucketing):
    • 목적: 데이터를 여러 개의 버킷(태블릿)으로 분할하고, 이 버킷들을 클러스터 내의 여러 BE 노드에 분산시켜 병렬 처리 성능을 극대화하는 것입니다.
    • 설계: 버킷팅 키(분산 키)를 해시(Hash)하여 데이터를 각 버킷에 할당합니다. 데이터가 모든 노드에 고르게 분포되도록, 카디널리티가 높은 컬럼을 버킷팅 키로 선택하는 것이 중요합니다.

🤔 꼬리 질문: 파티셔닝과 버킷팅은 어떤 차이가 있을까요? 만약 버킷팅 키를 잘못 선택하여 데이터가 특정 노드로 쏠리는 '데이터 스큐(Data Skew)' 현상이 발생하면, 쿼리 성능에 어떤 영향을 미치며 이를 어떻게 해결할 수 있을까요?


4. StarRocks 성능 최적화 실전 전략 ⚡

StarRocks의 성능을 최대한으로 끌어올리기 위해서는 다음과 같은 전략들을 종합적으로 고려해야 합니다.

  1. 사용할 스토리지 타입에 맞는 최적화 전략 선택:
    • 네이티브 스토리지 (Shared-nothing): BE 노드가 데이터 샤딩을 전담하므로, 데이터가 각 BE에 고르게 분산되도록 버킷팅 키를 신중하게 설계하고, SELECT 쿼리 조건에 맞는 정렬 키를 설정하여 데이터 프루닝 효과를 극대화합니다.
    • 네이티브 스토리지 (Shared-data): 분산 스토리지(S3 등)의 높은 처리량을 활용하며, 자주 사용되는 데이터(Hot Data)를 BE 노드에 캐싱하여 성능을 개선합니다. 컴팩션을 통해 분산 스토리지상의 순차 I/O를 유도하여 스몰 파일 문제를 완화합니다.
    • 외부 카탈로그 (Iceberg, Hive 등): Iceberg의 파티션 프루닝, 정렬 순서(Write Order), Z-Ordering 및 Parquet 파일의 Predicate Pushdown 기능을 최대한 활용하여 파일 시스템 레벨에서 읽는 데이터 양을 최소화합니다. 데이터 캐시를 적극적으로 활용하여 외부 스토리지 접근을 줄입니다.
  2. 쿼리 패턴을 고려한 파티셔닝, 버킷팅, 정렬 키 설정:
    • 파티셔닝 키: WHERE 절에서 범위 조건으로 자주 사용되는 날짜 컬럼 등을 사용하여 파티션 프루닝이 효과적으로 일어나도록 설계합니다.
    • 버킷팅 키: 데이터가 모든 노드에 최대한 균등하게 분산될 수 있도록 카디널리티가 높은 컬럼을 선택합니다.
    • 정렬 키: WHERE 절의 필터링 조건과 일치시켜, 필요한 데이터 블록만 읽도록 설정하여 I/O를 최소화합니다.
  3. 데이터 스큐(Data Skew) 확인 및 병목 경감:
    • SHOW PARTITIONSSHOW TABLETS 명령어를 통해 각 파티션과 태블릿(버킷의 실제 저장 단위)에 저장된 데이터의 크기와 행 수를 주기적으로 확인합니다.
    • 특정 태블릿에 데이터가 몰려있다면, 버킷팅 키가 데이터를 균일하게 분산시키지 못하고 있다는 신호이므로, 버킷팅 키 변경을 고려해야 합니다.
  4. Materialized View 적극 활용:
    • 자주 사용되는 집계 쿼리, 복잡한 JOIN 결과, 반복적인 데이터 변환이 필요한 경우 Materialized View를 생성하여 미리 계산된 결과를 저장해 둘 수 있습니다.
    • StarRocks의 Materialized View는 단순히 쿼리 결과를 저장하는 것을 넘어, 원본 테이블에 대한 쿼리 시 옵티마이저가 자동으로 해당 Materialized View를 사용하여 쿼리를 재작성(Query Rewrite)함으로써, 원본 테이블에 대한 쿼리 성능까지 투명하게 개선하는 강력한 기능을 제공합니다. (단, Windows 함수 등 일부 제약 존재)
  5. 대량 쓰기 작업을 위한 적절한 파티셔닝:
    • 테이블의 파티션 수가 너무 많아지면 FE 노드가 관리해야 할 메타데이터 양이 증가하여 메모리 부하를 유발할 수 있습니다. 대량의 데이터를 장기간에 걸쳐 지속적으로 쓰는 작업의 경우, 너무 잘게 쪼개기보다는 일(Day), 주(Week), 월(Month) 등 비즈니스 요구사항에 맞는 적절한 파티션 단위를 선택하는 것이 중요합니다.
  6. 모니터링 및 쿼리 분석:
    • StarRocks는 Grafana 대시보드 템플릿을 공식적으로 제공하므로, 이를 활용하여 클러스터 상태, 컴팩션 현황, 각 노드의 리소스 사용량 등을 지속적으로 모니터링해야 합니다.
    • AuditLoader와 같은 도구를 사용하여 느린 쿼리(Slow Query)를 분석하고, 실행 계획을 확인하여 병목 지점을 찾아 최적화합니다.

마치며: 클라우드 네이티브 시대의 OLAP 엔진

'잘' 운영하기 위해서는 다양한 기술적 선택지 중에서 서비스의 요구사항과 특성에 맞는 최선의 선택을 내리는 것이 중요합니다. 데이터베이스 기술은 본격적으로 클라우드 환경에 맞춰 진화하고 있으며, 단순히 기존의 온프레미스(On-premise) 구조를 클라우드로 옮기는 것을 넘어, 클라우드 네이티브 환경에서 새롭게 개발되고 있습니다.

StarRocks 역시 동적 스케일링, 오브젝트 스토리지를 활용한 연산/스토리지 분리 등 클라우드 환경에 최적화된 기능들을 지속적으로 발전시키고 있습니다. Kubernetes 환경에서는 Operator를 활용하여 배포 및 관리를 자동화할 수 있지만, 그만큼 업그레이드나 장애 발생 시 대응 방안을 사전에 철저히 수립하는 고민이 필요합니다.

이 글이 고성능 OLAP 엔진, 특히 StarRocks를 이해하고 실제 시스템에 도입하여 성능을 최적화하는 데 도움이 되었기를 바랍니다.

참고:

  • LSM-Tree (Log-Structured Merge Tree): '흩어져 있는 데이터 변경 사항을 메모리에서 정렬한 후, 이를 디스크에 순차적으로 기록하고, 백그라운드에서 여러 개의 작은 파일들을 하나의 큰 정렬된 파일로 병합하는 기술'로, 쓰기 성능을 극대화하기 위해 많은 현대 데이터베이스(ClickHouse, RocksDB, HBase, Cassandra 등)에서 사용되는 핵심 스토리지 엔진 구조입니다.
  • CBO (Cost-Based Optimizer): 데이터에 대한 통계 정보(테이블 크기, 카디널리티, 데이터 분포 등)를 기반으로 여러 가능한 쿼리 실행 계획들의 비용을 예측하고, 가장 비용이 적게 드는 최적의 실행 계획을 선택하는 쿼리 옵티마이저입니다. StarRocks는 강력한 CBO 성능을 주요 특징 중 하나로 내세우고 있습니다.

0개의 댓글