TECH 으로 돌아가기
TECH HACKER NEWS 오늘 9분 읽기 20 READS

페타바이트급 ClickHouse를 5년 운영하며 배운 것들: MergeTree를 이해하면 절반은 끝나요

페타바이트급 ClickHouse를 5년 운영하며 배운 것들: MergeTree를 이해하면 절반은 끝나요
SOURCE IMAGE · HACKER NEWS
페타바이트급 ClickHouse를 5년 운영하며 배운 것들: MergeTree를 이해하면 절반은 끝나요

무슨 일이 있었나요

실시간 분석 플랫폼 Tinybird의 엔지니어가 5년 동안 페타바이트 규모의 ClickHouse 클러스터를 운영하면서 배운 교훈을 정리한 글을 올렸어요. Tinybird는 ClickHouse를 기반으로 만든 서비스라서, 이 팀은 말 그대로 ClickHouse로 먹고사는 사람들이거든요. 문서에는 안 나오지만 운영해보면 반드시 부딪히는 문제들이 많이 담겨 있어서, ClickHouse를 쓰고 있거나 도입을 고민하는 분들이 읽어보면 좋을 내용이에요.

ClickHouse가 뭐냐면

혹시 처음 들어보시는 분을 위해 짧게 설명하면, ClickHouse는 러시아 얀덱스에서 시작된 오픈소스 컬럼 지향 데이터베이스예요. 컬럼 지향이 뭐냐면, 일반적인 MySQL이나 PostgreSQL은 데이터를 행 단위로 저장하는데, ClickHouse는 열 단위로 저장해요. 그래서 '지난 한 달 동안 국가별 매출 합계' 같은 집계 쿼리를 돌릴 때 필요한 컬럼만 읽으면 되니까 수십 배에서 수백 배 빠르거든요. 대신 행 하나를 수정하거나 삭제하는 작업은 굉장히 서툴러요. 로그, 이벤트, 지표처럼 한 번 쓰고 많이 읽는 데이터에 딱 맞는 도구예요.

핵심 교훈: 모든 문제는 파트와 머지에서 시작해요

ClickHouse의 기본 테이블 엔진 이름이 MergeTree인데, 이 이름을 이해하면 운영 문제의 절반은 이해한 거예요. 데이터를 INSERT하면 ClickHouse는 그걸 바로 기존 데이터에 끼워 넣지 않고, 디스크에 파트(part)라는 새 덩어리를 하나 만들어요. 그리고 백그라운드에서 작은 파트들을 계속 합쳐서(merge) 큰 파트로 만들어요. 마치 책상 위에 서류를 일단 쌓아두고, 틈날 때마다 정리해서 파일 캐비닛에 넣는 것과 비슷해요.

여기서 운영자들이 가장 많이 겪는 사고가 나와요. 행을 한 건씩 자주 INSERT하면 파트가 초당 수백 개씩 생기고, 머지가 따라가지 못하면 'Too many parts' 에러가 뜨면서 쓰기가 멈춰요. 그래서 대원칙은 배치로 크게, 덜 자주 넣기예요. 수천에서 수만 행을 모아서 한 번에 넣거나, 그게 어려우면 서버 쪽에서 모아주는 async insert 설정을 쓰는 거예요. 파티션도 마찬가지예요. 날짜별로 파티션을 나누는 건 좋은데, 시간 단위나 고객 ID 단위로 잘게 쪼개면 파트 수가 폭발해서 똑같은 문제를 겪어요.

정렬 키 설계가 성능의 대부분을 결정해요

ClickHouse에는 전통적인 의미의 인덱스가 없어요. 대신 테이블을 만들 때 ORDER BY로 지정한 컬럼 순서대로 데이터를 정렬해서 저장하고, 8,192행마다 하나씩 '이 구간의 첫 값은 이거다'라는 표시만 남겨요. 이걸 희소 인덱스(sparse index)라고 하는데요. 쿼리의 WHERE 조건이 이 정렬 키 앞부분과 맞으면 관련 없는 구간을 통째로 건너뛸 수 있어서 빠르고, 안 맞으면 전체를 훑어야 해요. 그래서 정렬 키는 값의 종류가 적은 컬럼과 자주 필터하는 컬럼을 앞에 두는 게 정석이고, 나중에 바꾸려면 테이블을 통째로 다시 만들어야 하니까 처음에 신중하게 정해야 해요.

수정과 삭제는 다른 방식으로 생각해야 해요

ALTER TABLE ... UPDATE나 DELETE는 ClickHouse에서 뮤테이션이라고 부르는데, 이게 뭐냐면 해당 파트 전체를 다시 쓰는 작업이에요. 행 하나 고치려고 수 기가바이트 파트를 통째로 재작성하는 거죠. 그래서 운영 팀들은 아예 다른 접근을 써요. ReplacingMergeTree로 같은 키의 최신 버전만 남기게 하거나, TTL로 오래된 데이터를 자동 삭제하거나, 아니면 파티션 단위로 DROP PARTITION 하는 식으로요. 다만 ReplacingMergeTree의 중복 제거는 머지가 일어날 때 비로소 적용되는 최종적 일관성이라서, 쿼리 시점에 정확한 결과를 원하면 FINAL 키워드를 써야 하고 그건 또 느려요. 이 트레이드오프를 모르면 '왜 중복이 남아 있지?' 하고 한참 헤매게 돼요.

복제와 Keeper, 그리고 메모리

여러 대로 클러스터를 구성하면 ReplicatedMergeTree를 쓰는데, 복제 상태를 조율하는 데 ClickHouse Keeper(예전엔 ZooKeeper)가 필요해요. 파트가 많아질수록 Keeper에 저장되는 메타데이터도 늘어나서, 페타바이트 규모에서는 Keeper 자체가 병목이 되는 경우가 있어요. 그리고 메모리 문제도 빼놓을 수 없는데요. ClickHouse의 JOIN은 기본적으로 오른쪽 테이블을 통째로 메모리에 올리는 방식이라, 큰 테이블 두 개를 무심코 조인하면 OOM으로 서버가 죽어요. 그래서 쿼리별 메모리 상한을 반드시 걸고, 조인은 작은 테이블을 오른쪽에 두거나 사전(dictionary) 기능으로 대체하는 게 관행이에요. 운영 상태는 system.parts, system.merges, system.query_log 같은 시스템 테이블을 주기적으로 조회해서 모니터링하고요.

업계 맥락

ClickHouse는 지난 몇 년 사이 실시간 분석 분야의 사실상 표준이 됐어요. 경쟁자로는 Apache Druid, Apache Pinot, StarRocks 같은 프로젝트가 있는데요. Druid와 Pinot은 스트리밍 수집에 특화된 대신 운영 컴포넌트가 많고, ClickHouse는 단일 바이너리로 시작할 수 있을 만큼 단순하면서 SQL 호환성이 좋아서 채택이 빨랐어요. Snowflake나 BigQuery 같은 클라우드 웨어하우스와 비교하면, ClickHouse는 초 단위 응답이 필요한 사용자 대면 대시보드에 강하고 저쪽은 대규모 배치 분석에 강하다고 보면 돼요.

한국 개발자에게 주는 시사점

국내에서도 게임사 로그 분석, 광고 플랫폼 지표, 핀테크 거래 모니터링 같은 곳에서 ClickHouse 도입이 꽤 늘었어요. 이제 막 도입하려는 팀이라면 이 글의 교훈을 체크리스트로 삼으면 좋아요. 배치 INSERT, 파티션 최소화, 정렬 키 신중하게, 뮤테이션 피하기, 메모리 상한 설정. 이 다섯 가지만 지켜도 흔한 장애의 대부분은 피할 수 있어요. 그리고 직접 운영이 부담스럽다면 ClickHouse Cloud나 Tinybird 같은 관리형 서비스를 쓰는 것도 현실적인 선택이에요.

마무리

한 줄로 정리하면, ClickHouse는 파트와 머지라는 동작 원리를 이해하고 그에 맞게 데이터를 넣는 팀에게는 놀라운 속도를 주지만, 일반 RDB처럼 다루는 팀에게는 계속 장애를 안겨주는 도구예요. 여러분 팀은 분석 DB로 뭘 쓰고 계세요? ClickHouse 운영하면서 겪은 사고담이 있다면 공유해주세요.


🔗 출처: Hacker News

SOURCE · HACKER NEWS
원문 전체 보기 → https://www.tinybird.co/blog/what-i-learned-operating-clickh...
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기
처리 중...