3. D1과 ClickHouse의 역할 분리

처음에는 당연하게 단일 데이터베이스를 생각했다. 이때는 분석 데이터의 특징에 대해서 잘 알지 못했기에 어떠한 유형이든 상관없이 모든 데이터를 하나의 저장소로 관리하는게 편하기 때문에 별도로 데이터베이스를 나눌 생각을 하지 않았다.

D1 선택 이유

항상 supabase를 기본으로 사용해 왔었는데 이번에는 D1을 선택했다. Supabase의 성능이 부족해서가 아니다.

데이터는 그리 크지 않은 관계형 데이터였고 Supabase도 적합했지만 API가 cloudflare workers로 동작하기 때문에 D1을 사용하면 운영 구조를 Cloudflare 생태계 안으로 단순화할 수 있다고 보았다. 또한, D1은 Worker에서 binding으로 직접 접근할 수 있어서 별도의 URL과 API Key로 관리하지 않아도 되어 굉장히 단순하게 사용할 수 있고, 아직 베타 단계이지만 Global Read Replication을 제공하기 때문에 전 세계에 분산된 읽기 요청의 지연을 줄일 수 있다고 보았다.

D1의 쓰기 병목

D1은 쓰기 병목이 심하다는 걸 알게됐다. D1 데이터베이스는 기본적으로 single-threaded로 동작하며, 한 번에 하나의 쿼리를 처리한다. 따라서 처리량은 데이터베이스가 얼마나 빠른지보다 각 쿼리가 얼마나 오래 걸리는지에 직접적인 영향을 받는다. 평균 쿼리 시간이 1ms라면 대략 초당 1,000개, 100ms라면 초당 10개 정도의 처리량이 가능하다. Cloudflare D1 Limits

일반적인 CRUD 요청에서는 큰 문제가 아닐 수 있고, 적절한 인덱스를 사용해 사용자 한 명이나 사이트 한 건을 조회하는 쿼리는 빠르게 끝날 것이라고 보았다. 사이트 정보와 관련한 쓰기 요청은 일반적인 요청들과 비슷하게 빈도가 그리 많지는 않지만 분석 데이터가 관건이었다.

분석 이벤트는 일반적인 이벤트와 다르다. 게시글 하나를 작성하거나, 프로필을 수정하는 일반적인 쓰기 요청과 다르게 분석 이벤트는 매 페이지를 이동할 때 마다 쓰기를 요청한다. 읽기 보다는 쓰기가 자주 발생하는 데이터인 셈이다. 그리고 동시 접속자 수에 이벤트 수는 비례하고 쓰기 요청도 이에 따라 빈도가 늘어나게 된다.

나만 사용하기 위해 만들 서비스라면 D1도 충분하다고 보았지만, 상용화를 목적에 두었기에 사이트 정보 관리와 방문 이벤트 집계가 같은 데이터베이스에서 계속 경쟁해도 괜찮은가?에 대해 고민이 필요했다. 하지만 질문에 대해 확신이 없어서 비슷한 서비스들은 어떤 구조를 택했는지 찾아보았는데 기존에 PostgreSQL이나 MongoDB를 사용하다가 분석 부하의 문제를 발견하고 ClickHouse로 이관한 서비스들을 알게 되었다.

그래서 ClickHouse에 대해 찾아보았다.

ClickHouse는 일반 데이터베이스와 다른 점

ClickHouse 공식 문서는 ClickHouse를 column-oriented SQL database management system이라고 설명한다. 일반적인 트랜잭션 처리, 즉 OLTP는 한 번에 적은 수의 행을 읽고 쓰는 작업에 가깝다. 반면 OLAP는 대량의 데이터를 읽고 집계하는 작업에 가깝다. What is ClickHouse?

예를 들어 일반적인 row-oriented 데이터베이스에서는 한 행의 값들이 함께 저장된다.

event_id | site_id | occurred_at | path | country | browser | device

특정 이벤트 한 건을 찾는 작업에는 이런 구조가 자연스럽다. 한 행에 필요한 값들이 모여 있기 때문이다.

반면 국가별 방문 수를 구하는 쿼리를 생각해보면 다르다.

SELECT
  country,
  count() AS visits
FROM page_event
WHERE site_id = {siteId:String}
  AND occurred_at >= {from:DateTime}
  AND occurred_at < {to:DateTime}
GROUP BY country
ORDER BY visits DESC;

이 쿼리에 필요한 것은 site_id, occurred_at, country다. path, browser, device 같은 값은 이번 집계에 필요하지 않다.

ClickHouse는 데이터를 열 단위로 저장하기 때문에 이런 분석 쿼리에서 필요한 열만 읽는 데 유리하다. ClickHouse 공식 문서도 column-oriented storage에서는 쿼리에 필요한 열만 디스크에서 읽어 사용하지 않는 열에 대한 I/O를 줄일 수 있다고 설명한다. 이것이 ClickHouse가 모든 작업에서 일반 데이터베이스보다 빠르다는 뜻은 아니다. 한 명의 사용자를 찾거나, 사이트 설정 한 건을 수정하거나, 여러 테이블의 관계를 자주 변경하는 작업에는 일반적인 관계형 데이터베이스가 더 자연스러울 수 있다.

ClickHouse가 잘 맞는 지점은 대량의 이벤트에서 특정 열을 기준으로 필터링하고, 그룹화하고, 집계하는 작업이다. 분석 서비스의 대시보드가 필요로 하는 작업과 겹치는 부분이 많다. 그래서 데이터의 역할을 다음처럼 나누는 방향을 고려했다:

D1
  사이트, 사용자, 설정과 같은 애플리케이션의 기준 데이터

ClickHouse
  방문 이벤트와 세션, 기간별·차원별 분석 데이터

이 구조는 오히려 D1이 잘하는 일을 그대로 맡기고, 분석 데이터만 ClickHouse로 분리하는 것이다.

로컬 성능 측정

일단, ClickHouse를 사용하기로 했는데 단순히 위에 있는 정보만으로는 좋은지 안좋은지 알 수 없어서 로컬 환경에서 테스트를 해봤다. *운영 환경에서는 사용량 초과하면 쫄쫄 굶어야 하기 때문에 로컬 환경 테스트 진행

실행 환경

데이터

읽기

쿼리D1ClickHouse결과
전체 스캔·좁은 컬럼261ms152msClickHouse 1.7배
전체 스캔·넓은 컬럼337ms189msClickHouse 1.8배
site 필터 조회23ms72msD1 3.1배
site breakdown25ms75msD1 3.0배

쓰기

방식D1ClickHouse결과
50만 건 bulk load5.51초0.93초ClickHouse 5.9배
200건 단건 commit2.10초15.10초D1 7.2배
100건 batch2.16초0.23초ClickHouse 9.6배
1,000건 batch2.09초0.15초ClickHouse 14배
ClickHouse async + 200개 단건2.16초14.94초이 테스트에서는 D1 우세

해석

결과가 일반적인 ClickHouse 특성과 맞는다.

따라서 현재 신뢰할 수 있는 결론은:

ClickHouse는 “모든 쓰기와 모든 조회가 빠른 DB”가 아니라, 대량 이벤트 저장과 대규모 분석 조회에 유리한 DB다.

*운영환경에서는 결과가 달라질 수 있다.

운영 성능 측정 예상

읽기

workload로컬 결과운영 예상
전체 기간 대량 스캔ClickHouse 1.7~1.8배데이터·동시성이 커질수록 ClickHouse 우세 확대 가능
site/date 소량 조회D1 약 3배단일 요청은 D1 우세 가능하지만, 원격 latency가 차이를 줄일 수 있음
breakdown/group byD1 우세데이터가 작으면 D1, 전체 기간·고동시성에서는 ClickHouse가 유리할 가능성
rollup 조회D1 우세 예상rollup이 작으면 D1 우세 유지 가능. 동시 요청이 많으면 ClickHouse가 역전 가능

D1은 운영에서 데이터베이스별로 쿼리를 사실상 순차 처리하므로, 동시에 여러 dashboard 요청이 들어오면 대기열과 p95가 커질 수 있다. Cloudflare도 D1의 처리량이 쿼리 시간에 직접 좌우되고, 데이터베이스가 단일 스레드로 동작한다고 설명한다. D1 limits

ClickHouse는 운영 네트워크 latency가 추가되지만, 쿼리 내부에서 여러 CPU를 활용해 넓은 범위를 병렬 스캔할 수 있어서, 결과가 작은 aggregate query라면 네트워크 비용은 상대적으로 작고, 대량 스캔에서는 ClickHouse의 이점이 유지될 가능성이 높다.

쓰기

workload로컬 결과운영 예상
단건 동기 쓰기D1 우세낮은 트래픽에서는 D1이 여전히 단순할 수 있음. 다만 원격 D1 latency가 추가됨
100건 배치ClickHouse 약 10배Queue 배치 적재라면 ClickHouse 우세 가능성 높음
1,000건 배치ClickHouse 약 14배ClickHouse 우세가 더 커질 가능성
세션 상태 update미측정낮은 빈도 update는 D1, 고량 append/update는 ClickHouse 설계에 따라 달라짐
삭제·대규모 정정미측정소규모 즉시 삭제는 D1, 대규모 삭제는 ClickHouse mutation 비용 확인 필요