ClickHouse 오픈소스 10년
(clickhouse.com)- ClickHouse는 2016년 6월 15일 공개된 뒤 10년 동안 2,000명 이상이 기여하며 오픈소스 분석 데이터베이스의 대표 프로젝트로 성장함
- 단순 코드 공개가 아니라 기여 가이드, 코드 리뷰, 로드맵, CI, 릴리스, 문서까지 공개하는 Level 3 오픈소스를 지향함
- 출발점은 MySQL 기반 웹 분석 시스템의 한계였고, OLAPServer와 Metrage의 경험이 컬럼 지향 처리와 MergeTree 설계로 이어짐
- ClickHouse는 기존 DBMS 위의 확장이 아니라 2009년부터 컬럼 표현, 집계 함수, 테이블 엔진, 압축, SQL 파서, 서버·클라이언트, ReplicatedMergeTree를 단계적으로 만든 처음부터 구현한 DBMS임
- 2014년 사내 프로덕션에서 매일 수천억 레코드를 처리한 뒤, 2015년 공개 글과 내부 승인 과정을 거쳐 2016년 전 세계에 공개됨
오픈소스 공개 10년
- ClickHouse는 2016년 6월 15일 오픈소스로 공개됨
- 이후 2,000명 이상이 기여했고, “가장 인기 있는 오픈소스 분석 데이터베이스”가 됨
- 프로젝트의 핵심 목표는 코드만 공개하는 데 그치지 않고 개발 과정과 기여 과정을 최대한 공개하는 것임
ClickHouse가 지향하는 오픈소스 수준
- 오픈소스에는 여러 수준이 있음
- ClickHouse는 Level 3 오픈소스를 지향함
- 새 데이터베이스를 만들려는 개발자가 참고할 수 있는 코드와 개발 관행의 예시가 되는 것도 목표임
- 코드는 모듈형, 직교적, 문서화된 형태를 지향함
- 복잡한 개념이 필요할 때는 주석에서 처음부터 설명해 독자가 교과서, Wikipedia, AI를 참조하지 않아도 되도록 함
C++ 개발과 성능 실험의 장
- ClickHouse는 인기 있는 C++ 오픈소스 저장소 중 하나로, C++23 같은 최신 언어 기능과 빌드 시스템, 지속적 통합·테스트, 코드 리뷰 관행 같은 기반 작업을 함께 배울 수 있는 장소를 지향함
- 데이터 구조와 성능 최적화 실험도 중요한 사용 방식임
- 병합을 목표로 하지 않는 실험적 Pull Request도 프로덕션 릴리스와 같은 수준으로 테스트됨
- 새 메모리 할당기, 압축 라이브러리, 해시 테이블, 데이터 포맷, 정렬 알고리듬 같은 실험을 ClickHouse에서 검증할 수 있음
- 로드맵에는 실험적이고 이상하며 심지어 우스꽝스러운 항목도 포함됨
- 모든 기여자는 CHANGELOG와 데이터베이스 내부 system.contributors 테이블에서 크레딧을 받음
- 초기 구현이 불완전한 기능도 함께 완성하는 사례가 많고, 코드 전체를 다시 작성해야 해도 초기 작성자의 의도와 사용 사례를 인정함
ClickHouse 이전의 문제와 프로토타입
- ClickHouse의 첫 커밋은 2009년 5월 29일 만들어졌고,
localtime,mktime,gmtime같은 libc 함수가 너무 느려 프로파일러에 나타나는 문제를 줄이기 위한 성능 최적화였음 - 출발점은 웹 분석 시스템의 데이터 처리 실험이었음
- 시스템은 Google Analytics와 비슷하게 웹사이트에서 전송된 페이지뷰 로그를 받음
- MySQL, C++ 데이터 처리, MySQL로 충분하지 않은 영역의 커스텀 C++ 데이터 구조를 함께 사용함
- MySQL 데이터베이스는 고객용 사전 집계 리포트를 저장했고, 커스텀 데이터 구조는 사용자 세션과 사용자 히스토리 계산에 쓰임
- 데이터는 계속 늘고 새 로그는 실시간으로 들어왔으며, 5분 단위 로그를 5분 안에 처리하지 못하면 지연이 계속 쌓였음
- 여러 데이터베이스와 라이브러리도 시도함
- TokuDB, LMDB, Judy Arrays, Hadoop, LZO, QuickLZ, HyperLogLog, 데이터 압축 자료, 이벤트 루프 서버 문서 등을 검토함
- 사용자가 임의의 리포트를 구성하게 하려는 요구가 사전 집계 리포트의 한계를 드러냈고, 컬럼 지향 데이터베이스 검토로 이어짐
OLAPServer와 Metrage
- 컬럼 지향 접근은 비집계 구조화 로그를 저장한 뒤, 고객이 페이지 로드를 기다리는 동안 즉석에서 집계하는 방식이었음
- MySQL 확장인 Infobright, InfiniDB와 독립 분석 데이터베이스인 Vertica, MonetDB, LucidDB를 테스트했지만, 하루 1,000억 레코드와 500개 컬럼 로딩 조건에서는 동작하지 않았음
- 첫 커스텀 프로토타입은 OLAPServer였음
- 2008년 12월 구현되고 2009년 1월 배포됨
- 모든 컬럼을 하루·웹사이트별 단일 바이너리 파일에 저장함
- 문자열 대신 해시를 쓰고, 정수 타입만 지원함
- 가벼운 압축을 사용하고, 하루 한 번 몇 시간 지연을 두고 갱신됨
- 그룹화 컬럼, 집계 함수, 필터, 정렬을 지정하는 API를 제공했고 쿼리는 XML로 지정됨
- 과거 MySQL 집계 데이터를 “비집계화”해 동일한 결과가 나오도록 채우는 작업은 Evgenii Gatov가 해결함
- OLAPServer는 전사 인터넷 데이터를 단일 웹사이트가 아니라 전체적으로 분석하는 엔드포인트에서도 작동했고, 사내 분석가들이 내부 MapReduce 대신 사용할 만큼 즉시 응답했음
- 두 번째 프로토타입은 Metrage였음
- MySQL에 약 50TB 데이터가 50개 샤드로 쌓였고, 많은 커스텀 데이터 구조가 BLOB로 저장됨
- 집계 시 프로그램이 BLOB를 읽고 커스텀 코드를 적용한 뒤 다시 삽입해야 했음
- MySQL 데이터는 압축되지 않았고, 도착 순서와 쿼리 범위 순서가 맞지 않아 읽기도 느렸음
- Metrage는 백그라운드 병합을 사용하는 증분 집계용 커스텀 데이터 구조였고, 각 레코드는
add,update,merge,serializeText/Binary,deserializeText/Binary메서드를 가진 C++ 구조체로 정의됨
- OLAPServer는 비집계 컬럼 지향 구조였고, Metrage는 임의 CRDT를 가진 실시간 행 지향 구조였음
- ClickHouse는 컬럼 지향 집계 속도와 merge tree 기반 실시간 갱신·데이터 지역성을 결합하고, 실제 쿼리 언어와 데이터 타입을 지원하도록 일반화하면서 시작됨
처음부터 만든 DBMS
- ClickHouse는 기존 데이터베이스 기반이 아니라 처음부터 구현된 드문 DBMS 사례임
- 2009년 초기 커밋은 같은 모노리포지터리 안의 다른 데이터 구조 최적화와 관련된 것이며, 오픈소스 공개 과정에서 히스토리를 보존해 저장소를 분리했기 때문에 남아 있음
- 새 DBMS 구현의 첫 단계는 메모리 내 컬럼 구현이었고, 오늘날에도 익숙한
IColumn과Field클래스가 등장함- Apache Arrow와 비슷해 보일 수 있지만, 당시 Apache Arrow는 존재하지 않았음
- RCFile, Trevni, ORC, Parquet 같은 다른 컬럼 지향 포맷도 당시에는 존재하지 않았음
- 이후 집계 함수가 도입됐고, 현재도 ClickHouse의 가장 중요한 부분 중 하나임
- 테이블 엔진도 도입됨
- 처음에는 “primary key”라는 이름을 며칠간 사용함
- 디스크에서 컬럼을 읽고 쓰는 기능을 가능하게 함
- 첫 테이블 엔진은 오늘날까지 존재하는 TinyLog와 비슷했음
- 압축은 처음에 QuickLZ를 사용했지만, Yann Collet의 블로그를 읽은 뒤 LZ4로 교체됨
쿼리 파이프라인과 SQL 구현
- block streams는 컬럼 청크를 스트리밍 형태로 생산, 소비, 변환하는 데이터 처리 파이프라인 컴포넌트였음
- 현재는 Processors로 대체됨
- 결과 포맷팅과 테이블 쿼리 구현의 기반이 됨
- 같은 커밋에서
StorageSystemNumbers가 테스트용으로 추가됐고, 오늘날의system.numbers테이블로 남아 있음 - 첫 쿼리 파이프라인은 TSV로 숫자를 출력하는 것이었고, 첫 관계형 연산자는
LIMIT이었음 - SQL 파서는 처음 boost::spirit을 시도했지만 실패했고, 이후 재귀 하강 파서를 만들었음
- 초기에 도입했다가 제거되거나 나중에 다시 도입된 아이디어도 있음
- 가변 길이 인코딩 숫자 컬럼은 느려서 제거됐고, 훨씬 나중에 컬럼과 독립된 커스텀 압축 코덱이 도입됨
- 임의 필드 값을 담는
Variant컬럼 타입도 느려 제거됐고, 더 나은 Variant는 2025년에 추가됨 - 고정 크기 배열 타입은 필요성이 낮아 제거됐고, 현재 다시 추가가 검토되고 있음
- 불필요한 코드를 제거하는 것이 새 코드를 추가하는 것보다 중요하다는 개발 원칙이 드러남
프로덕션 배포와 ReplicatedMergeTree
- ClickHouse에서 테스트된 첫 실제 테이블 구조는
hits테이블이며, 오늘날 ClickBench에서도 볼 수 있음 - 이 테이블을 읽고 쓰는 과정에서 C++ iostreams가 느리다는 점이 드러났고,
WriteBuffer와ReadBuffer가 도입되어 현재도 사용됨 - SQL의 첫 함수는 산술 연산자였고, 이를 통해 첫
SELECT쿼리 인터프리터가 구현됨 - ClickHouse 서버는 2012년 3월 9일,
clickhouse-client는 2012년 3월 25일 도입됨 Log,TinyLog,Merge,Distributed,Memory테이블 엔진과 함께 프로덕션 배포가 가능해짐- 첫 프로덕션 용도는 추가 처리를 위한 로그 청크 저장과 원시 로그 위의 전역 쿼리였음
- SQL 쿼리가 가능한 영속 로그 큐처럼 사용됐음
- 이후 MergeTree가 추가됨
- 데이터가 시간순으로 들어와도 백그라운드에서 증분 정렬을 수행함
- 단일 웹사이트에 대한 범위 쿼리를 빠르게 처리할 수 있게 함
- OLAPServer와 Metrage를 대체하는 프로덕션 배포가 가능해짐
- 2012년 Michael Kolupaev가 팀의 두 번째 직원으로 합류했고, ReplicatedMergeTree 구현에 참여함
- 프로덕션은 여러 지역 데이터센터에 배포됐고, 인프라 팀은 한 달에 한 번 데이터센터를 한 시간 동안 끄는 “drills”를 수행함
- 모든 프로덕션 서비스는 다중 데이터센터 복제를 갖춰야 했음
- 초기에는 단순 double-write와 다운타임 이후 backfill을 사용함
- 100% 일관성과 자동 복구를 위해 분산 합의가 필요했음
- ZooKeeper를 메타데이터 계층으로 사용한 ReplicatedMergeTree가 구현됨
- ReplicatedMergeTree는 2014년 사용자 대면 쿼리를 위한 ClickHouse 프로덕션 배포를 가능하게 함
오픈소스 공개까지의 과정
- 2014년 ClickHouse는 프로덕션에서 매일 수천억 레코드를 저장하고 고객의 실시간 쿼리에 응답함
- 회사 내부 데이터 과학자들은 ClickHouse로 인터넷 트렌드를 계산했고, 단순한 사용 문서도 공개됨
- 광고, 이커머스, 인프라, 비즈니스 분석 같은 다른 부서도 ClickHouse를 시도했고, 내부 MapReduce, MySQL, Postgres에서 일부 사용 사례를 이전함
- 2014년 말 ClickHouse는 한 회사 안에서 널리 쓰였고, 예외적으로 CERN도 LHCb experiment 협력 과정에서 배포함
- 다른 회사 엔지니어들도 기존 데이터베이스가 사용 사례를 잘 처리하지 못해 OLAPServer나 Metrage와 비슷한 것을 만들고 있다는 점이 확인됨
- 2015년 ClickHouse에 대한 글과 번역이 공개되면서 관심이 더 확인됨
- 공개 전에는 회사 경영진을 설득하기 위해 잠재적 장점과 위험 목록을 준비함
- 승인을 받은 뒤 릴리스 계획, 첫 로고, 첫 웹사이트, 블로그 글, Debian 저장소가 준비됐고, ClickHouse는 2016년 6월 15일 전 세계에 공개됨
- 현재 ClickHouse는 전 세계 대기업들이 사용하는 인기 있는 분석 데이터베이스가 됨
댓글과 토론
Hacker News 의견들
-
2017~2018년쯤 ClickHouse를 발견하고 Elasticsearch를 대체하는 개념 검증을 만들었는데, 몇 주 만에 저장 공간과 초당 질의 수가 5배 좋아졌음
하지만 관리자들은 잘 알려지지 않았고 “러시아인이 만든 어떤 데이터베이스”처럼 보인다는 이유로 거절했음
개인적으로는 그렇게 일찍 기차가 오는 걸 보고도 올라타지 못한 게 꽤 아쉬움- 최근 비슷한 일을 겪었음. ClickHouse로 바꾸면 데이터베이스 운영이 60% 줄고, 시계열 데이터베이스가 필요 없어지며, 질의 시간이 약 300~500ms에서 대략 75ms로 줄어드는 것으로 나왔음
압축률도 말도 안 될 정도였고, 저장 비용 벤치마크는 S3 비용 수준까지 내려갔음
월 수백만 달러짜리 저장 계층이 월 수천 달러 단위로 줄어드는 결과였음
ClickHouse가 만병통치약은 아니지만, 데이터가 어떻게 접근되는지 이해하고 그에 맞게 배치할 수 있다면 엄청난 효율을 얻을 수 있음 - 우리도 Elasticsearch에 묶여 있어서 ClickHouse로 옮기고 싶지만, 기존 부하 때문에 아직 못 하고 있음
- 단순 grep식 검색에 쓴 건지, 아니면 BM25 같은 고급 검색이 필요했던 건지 궁금함
이해하기로는 ClickHouse는 grep 같은 검색에만 도움이 되는 편임 - 공급망 위험이 있음
- ClickHouse가 검색을 할 수 있는지 궁금함. 아니라면 왜 Elasticsearch를 대체하려 했는지 모르겠음
- 최근 비슷한 일을 겪었음. ClickHouse로 바꾸면 데이터베이스 운영이 60% 줄고, 시계열 데이터베이스가 필요 없어지며, 질의 시간이 약 300~500ms에서 대략 75ms로 줄어드는 것으로 나왔음
-
ClickHouse는 오랫동안 TimescaleDB를 쓰던 입장에서 정말 신선했음. psql은 최고이고, 하나의 데이터베이스 시스템에 전부 의존할 수 있다는 점도 좋았지만, 마이그레이션 유지보수와 배포 단계에서는 꽤 고통스러웠음
TimescaleDB는 버전마다 구조가 바뀌는 느낌도 있고, 개발 방향이 다소 흔들려서 가끔은 알파 품질 제품처럼 느껴짐- 아주 오래전에 TimescaleDB를 써봤고, 그 이후로 많이 바뀐 것 같음. 지금 구성에서는 PostgreSQL을 TimescaleDB로 올려서 오래된 데이터를 보관하고, 동시에 ClickHouse도 병렬 배포하는 방안을 생각 중임
PeerDB로 ClickHouse 미러를 크게 가져갈지, 아니면 추가 취약 계층 없이 별도로 배포할지 아직 고민 중임
TimescaleDB를 아예 추천하지 않는 편인지 궁금함. PostgreSQL은 현재 스택에서 가장 단단한 부분이라, 알파 품질 소프트웨어의 고통은 확실히 피하고 싶음 - PostgreSQL 생태계에서도 “하나의 시스템으로 전부 실행”을 가능하게 하려는 작업이 많이 진행 중임. ParadeDB는 색인 수준에서 전문 검색과 벡터 검색, 가벼운 집계를 밀고 있는 시스템 중 하나임
DuckDB 쪽에서도 pg_duckdb 작업이 있고, Xata 같은 곳도 있음
참고로 ParadeDB에서 일하고 있음
- 아주 오래전에 TimescaleDB를 써봤고, 그 이후로 많이 바뀐 것 같음. 지금 구성에서는 PostgreSQL을 TimescaleDB로 올려서 오래된 데이터를 보관하고, 동시에 ClickHouse도 병렬 배포하는 방안을 생각 중임
-
Cloud 66의 지표 및 자동 확장 엔진은 ClickHouse로 정착하기 전까지 5번의 반복을 거쳤음: Redis, Cassandra, Ruby+RabbitMQ 직접 구현, Go+RabbitMQ 직접 구현, 그리고 ClickHouse
매번 어떤 한계나 감당하기 어려운 최적화 부담에 부딪혔는데, ClickHouse는 지난 4년간 매우 안정적이었음- 어떤 문제를 풀고 있었는지 잘 그려지지 않음. Redis, Cassandra, RabbitMQ, ClickHouse 조합에서 RabbitMQ가 유난히 튀어 보임
-
ClickHouse로 Loki를 대체하고 나서야 관측성 스택이 드디어 “맞는” 느낌이 들었음. 로그와 일반적인 분석 질의에서 정말 강력함
- 우리도 LGTM을 전면적으로 쓰고 있는데 이건 흥미로움. 다만 Loki도 잘 쓰고 있어서, SQL이 LogQL보다 표현력이 좋다는 점 외에 ClickHouse가 더 나은 부분이 무엇인지 궁금함
- 시각화는 어떻게 하는지 궁금함. ClickStack을 쓰는지, 아니면 다른 걸 쓰는지 알고 싶음
-
좋은 OLAP 데이터베이스라는 점에 더해, 원격 소스에서 데이터를 가져오는 내장 커넥터가 게임 체인저였음
Parquet/JSON 파일이 들어 있는 S3 폴더를 주기적으로 자동 가져오기 할 수 있고, Postgres에도 직접 연결할 수 있음
중간 규모 신문사의 데이터 웨어하우스에서 Druid+Postgres+Trino 조합을 큰 ClickHouse 노드 하나로 바꿨고, 다시 돌아볼 일이 없었음
훨씬 빠르고 실용적이며 유지보수도 훨씬 적음 -
ClickHouse는 정말 마음에 들고 성능이 뛰어남. 여기저기 질의 몇 개를 성능 때문에 조정해야 했지만 전반적으로 기대 이상이었음
처음에는 큰 증분 적재를 처리하려고 실시간 파이프라인 수집을 구성했는데, 예전에 쓰던 Redshift는 비싸고 비교적 느렸음
지금까지는 ClickHouse가 많은 데이터와 큰 변환을 거뜬히 처리해서 그 파이프라인이 필요 없었음
유일한 문제는 기본 설정에서 꽤 무거운 추적 기능이 켜져 있었고, 상대적으로 작은 장비에서는 성능을 크게 떨어뜨렸다는 점임
이후 규모를 키웠고 이제는 데이터 스택의 핵심이 됨
정말 큰 규모라면 다른 것을 고를 수도 있겠지만, 몇 개 노드 수준에 머무는 한 복잡도는 관리 가능하고 쓰는 즐거움이 있음- 기본으로 켜져 있었다는 무거운 추적 기능이 무엇이었는지 궁금함
-
“머지될 것을 목표로 하지 않아도 실험으로 풀 리퀘스트를 열 수 있고, 운영 릴리스와 같은 수준의 검사를 받는다. 새로운 메모리 할당자, 압축 라이브러리, 해시 테이블, 데이터 형식, 정렬 알고리즘을 찾았나? ClickHouse로 가져오면 속속들이 드러나게 해준다”라니, 대단함
- ClickHouse 개발자인데, 이 말은 사실임. ClickHouse는 여러 서드파티 라이브러리의 버그를 찾는 데 기여했고, 내가 직접 다룬 것만 해도 jemalloc과 librdkafka가 있음
Linux 커널을 비롯해 사실상 여기저기서 버그를 찾아냄
매우 엄격한 퍼저가 있고, 여러 수준에서 여러 퍼저가 돌아가며, 말도 안 되게 많은 설정 조합으로 테스트를 실행함
1년쯤 전에 들은 마지막 수치는 풀 CI 실행이 단일 커밋 하나당 약 400시간이라는 것이었음
그래서 좋은 의미로 꽤 미친 수준임
- ClickHouse 개발자인데, 이 말은 사실임. ClickHouse는 여러 서드파티 라이브러리의 버그를 찾는 데 기여했고, 내가 직접 다룬 것만 해도 jemalloc과 librdkafka가 있음
-
블로그 글이 SQLite와 Ladybird는 스펙트럼에 올려두면서, 핵심 오픈소스 경쟁자인 DuckDB를 빼놓은 게 흥미로움
신뢰를 주는 건 3단계라는 데 동의함
하지만 바이브 코딩된 데이터베이스 시대에 지속 가능하려면 새로운 사업 모델을 발명해야 함- ClickHouse가 DuckDB보다 가진 주요 장점은 MergeTree 계열이라고 봄. 백그라운드에서 데이터를 정렬할 수 있고, 제대로 쓰면 터무니없는 수준의 압축률과 성능을 낼 수 있음
색인되지 않은 열을 질의할 때 ClickHouse는 Parquet를 질의하는 DuckDB보다 쉽게 10배 빠를 수 있고, 기본 키를 건드릴 때는 사실상 비교가 안 될 정도로 빠름
둘을 비교하는 글은 많지만 현실적으로 ClickHouse와 DuckDB는 완전히 다른 영역에 있음
DuckDB는 강력한 분석 엔진이고, ClickHouse는 복제와 MergeTree 엔진 등을 갖춘 완전한 데이터베이스 관리 시스템임 - ClickHouse는 작게 내려와 DuckDB와 경쟁할 수 있지만, DuckDB가 ClickHouse처럼 크게 확장될 수 있는지는 잘 모르겠음
대부분은 그런 규모 문제가 없지만, 생기면 차이가 큼
- ClickHouse가 DuckDB보다 가진 주요 장점은 MergeTree 계열이라고 봄. 백그라운드에서 데이터를 정렬할 수 있고, 제대로 쓰면 터무니없는 수준의 압축률과 성능을 낼 수 있음
-
페이지에서 “Google Analytics와 비슷한 웹 분석 시스템용 데이터 처리”가 실제로는 Yandex에서 쓰였던 것이라고 말하기를 꺼리는 점이 아쉬움
- 페이지 다른 곳에서도 Yandex 언급을 피하는 듯함. 실제로 Yandex를 한 번이라도 언급하는지 모르겠음
아마 그 회사를 광고하지 않으려는 의도일 텐데, 왜 그게 슬픈지는 잘 모르겠음
- 페이지 다른 곳에서도 Yandex 언급을 피하는 듯함. 실제로 Yandex를 한 번이라도 언급하는지 모르겠음
-
ClickHouse는 예전에 일했던 몇몇 회사에서 게임 체인저였음. Rust in Production 팟캐스트의 Rust 도입 에피소드가 떠오름
https://open.spotify.com/episode/0TBKDUhO0KihBxEzZqnQx1