Skip to content

ClickHouse on EKS 실측 벤치마크 퀴즈

  1. 벤치마크에서 1시간 창의 namespace + timestamp 범위 카운트(Q1)가 1억 행 테이블에서 4ms 만에 끝난 핵심 이유는 무엇인가요?
    • A) 결과가 이미 쿼리 캐시에 저장되어 있었기 때문에
    • B) PARTITION BY(일)와 ORDER BY(namespace, timestamp)의 프루닝으로 1억 행 중 16,385행만 읽었기 때문에
    • C) gp3 볼륨의 3,000 IOPS가 충분히 높았기 때문에
    • D) LowCardinality 타입이 비교 연산을 벡터화했기 때문에
정답 보기

정답: B) PARTITION BY(일)와 ORDER BY(namespace, timestamp)의 프루닝으로 1억 행 중 16,385행만 읽었기 때문에

설명: 쿼리 조건이 파티션 키(일 단위)와 정렬 키(namespace, timestamp)에 정확히 겹치면 ClickHouse는 primary index로 granule 단위 프루닝을 수행합니다. 이 벤치마크에서 쿼리 결과는 59,916행이었지만 실제로 읽은 행은 16,385행(0.016%)뿐이었습니다. primary key 범위 안에 완전히 들어가는 granule은 인덱스만으로 개수를 세고(ClickHouse 24.6+ 최적화), 범위 양끝에 걸친 granule만 압축을 풀어 읽기 때문입니다. ClickHouse 성능의 대부분은 이런 "읽지 않는 설계"에서 나옵니다.

  1. 컬럼별 압축 결과에서 trace_id는 1.0×(압축 불가), namespace는 약 201×로 나타났습니다. 이 차이를 만든 원인으로 옳은 것은?
    • A) trace_id 컬럼에만 압축 코덱이 지정되지 않았기 때문에
    • B) namespace가 문자열 길이가 더 짧기 때문에
    • C) 이 실행의 LZ4에서 trace_id는 반복 패턴이 적어 거의 줄지 않았고, namespace는 카디널리티가 낮은 데다 ORDER BY 첫 키라 같은 값이 길게 이어지기 때문에
    • D) namespace만 사전(dictionary) 파일이 별도로 생성되기 때문에
정답 보기

정답: C) 이 실행의 LZ4에서 trace_id는 반복 패턴이 적어 거의 줄지 않았고, namespace는 카디널리티가 낮은 데다 ORDER BY 첫 키라 같은 값이 길게 이어지기 때문에

설명: 이 실행의 LZ4에서 trace_id는 원시 약 3.07 GiB → 압축 후 약 3.08 GiB였습니다. hex 문자열은 한 문자에 4비트 정보만 담으므로 다른 코덱이나 바이너리 표현으로 줄일 여지가 있습니다. 반면 namespace는 값이 10종뿐인 LowCardinality 컬럼이며 정렬 첫 키라서 동일 값이 연속 블록으로 저장되어 95.72 MiB가 488.63 KiB(201×)로 줄었습니다. 로그 스키마에서 "ID를 어떻게 저장할 것인가"가 저장 비용의 최대 변수인 이유입니다.

  1. LZ4(기본)와 ZSTD(3)의 실측 비교 결과로 옳은 것은?
    • A) ZSTD(3)가 저장 공간과 스캔 속도 모두 우수했다
    • B) 저장 공간은 ZSTD(3)가 47% 작았지만, CPU-bound 풀스캔은 LZ4보다 약 1.9배 느렸다
    • C) 두 코덱의 저장 공간 차이는 5% 이내였다
    • D) LZ4가 저장 공간은 작았지만 스캔이 더 느렸다
정답 보기

정답: B) 저장 공간은 ZSTD(3)가 47% 작았지만, CPU-bound 풀스캔은 LZ4보다 약 1.9배 느렸다

설명: 실측에서 LZ4는 7.82 GiB(1.97×), ZSTD(3)는 4.16 GiB(3.7×)로 저장이 47% 절감됐지만, LIKE '%timeout%' warm 풀스캔은 2.63초 → 4.9초로 느려졌습니다. 최근 LZ4 + 오래된 파티션 TTL ZSTD는 후보 조합이며, 실제 데이터·CPU·I/O 비중으로 검증해야 합니다.

  1. LIKE '%timeout%' 풀스캔(Q3)이 페이지 캐시를 우회한 디스크 직행에서 31.5초 걸렸습니다. 이 수치가 말해주는 병목은 무엇인가요?
    • A) ClickHouse의 문자열 검색 알고리즘이 비효율적이다
    • B) message 컬럼 압축본 약 4 GiB ÷ 31.5초 ≈ 130 MiB/s로, 볼륨·인스턴스 EBS 경로의 처리량 제약과 일치하지만 단독 병목은 이 값만으로 구분할 수 없다
    • C) m5.xlarge의 4 vCPU가 포화된 것이다
    • D) EBS CSI 드라이버의 오버헤드가 지배적이다
정답 보기

정답: B) message 컬럼 압축본 약 4 GiB ÷ 31.5초 ≈ 130 MiB/s로, 볼륨·인스턴스 EBS 경로의 처리량 제약과 일치하지만 단독 병목은 이 값만으로 구분할 수 없다

설명: 같은 쿼리가 페이지 캐시에서는 2.63초(CPU-bound, 초당 약 3,800만 행)로 끝났습니다. 12배 차이는 캐시와 스토리지 경로의 영향을 보여 주지만, 물리 I/O와 CPU 지표 없이 gp3만 단독 병목이라고 증명할 수는 없습니다. gp3는 추가 비용으로 처리량을 최대 2,000 MiB/s까지 프로비저닝할 수 있습니다(그 수치에 닿으려면 IOPS도 8,000 이상이어야 합니다). 다만 이 m5.xlarge에서는 인스턴스의 EBS 베이스라인 약 137 MiB/s와 버스트 상태도 확인해야 합니다. 지속 수요가 이를 넘으면 노드와 볼륨을 함께 검토합니다.

  1. trace_id 점 조회(Q5)에 bloom filter skip index를 추가했을 때의 실측 변화로 옳은 것은?
    • A) 조회 시간 1.13초 → 0.036초(31배), 읽은 행 1억 → 108만(98.9% 스킵), 인덱스 크기는 테이블의 약 1.5%
    • B) 조회 시간은 그대로였지만 메모리 사용량만 줄었다
    • C) 조회 시간이 절반이 되었고 인덱스가 테이블 크기의 30%를 차지했다
    • D) ORDER BY 키를 바꾼 것과 동일한 효과로, 저장 공간도 함께 줄었다
정답 보기

정답: A) 조회 시간 1.13초 → 0.036초(31배), 읽은 행 1억 → 108만(98.9% 스킵), 인덱스 크기는 테이블의 약 1.5%

설명:bloom_filter(0.01) GRANULARITY 4 skip index는 각 granule 묶음에 대해 음성 결과가 나온 블록에는 해당 값이 없음을 판정하고, 양성은 false positive일 수 있어 대부분의 granule을 건너뜁니다. 실측에서 읽은 데이터가 3.82 GiB → 42.6 MiB로 줄었고, 인덱스 자체는 119.7 MiB(테이블의 1.5%), 기존 데이터 적용(MATERIALIZE)은 약 20초였습니다.

  1. 이 벤치마크의 ingest 수치(초당 약 94만 행)를 해석할 때 반드시 붙여야 하는 단서는 무엇인가요?
    • A) 복제본 3개 구성에서 측정한 값이라는 것
    • B) 서버 내부 INSERT…SELECT로 측정했으므로 외부 네트워크·파싱을 포함한 ingest 처리량을 직접 측정한 것은 아니라는 것
    • C) 메모리에만 쓰고 디스크에는 기록하지 않았다는 것
    • D) 압축을 끄고 측정한 값이라는 것
정답 보기

정답: B) 서버 내부 INSERT…SELECT로 측정했으므로 외부 네트워크·파싱을 포함한 ingest 처리량을 직접 측정한 것은 아니라는 것

설명: 데이터를 서버 안에서 생성해 바로 삽입했기 때문에 실제 외부 클라이언트가 TSV/Native로 밀어넣는 경로보다 유리한 조건입니다. 디스크 기록·정렬·압축은 모두 포함된 값이지만, 데이터 생성 CPU 비용도 포함하므로 외부 ingest의 수학적 상한은 아닙니다. 외부 클라이언트·배치·동시성·포맷으로 따로 측정해야 합니다.

  1. Q4(namespace별 duration p50/p99)는 1억 행 전체를 스캔하는데도 warm 기준 약 1초에 끝났습니다. 어떤 특성 덕분인가요?
    • A) 쿼리 결과가 머티리얼라이즈드 뷰에 미리 계산되어 있었기 때문에
    • B) 컬럼 지향 저장이라 duration_ms(289 MiB)와 namespace(0.5 MiB) 두 컬럼만 읽고, 테이블 전체 7.8 GiB는 읽지 않기 때문에
    • C) quantile이 디스크에서 8,192행만 읽고 나머지 행은 전혀 처리하지 않기 때문에
    • D) 파티션 프루닝으로 하루치 데이터만 읽었기 때문에
정답 보기

정답: B) 컬럼 지향 저장이라 duration_ms(289 MiB)와 namespace(0.5 MiB) 두 컬럼만 읽고, 테이블 전체 7.8 GiB는 읽지 않기 때문에

설명: 행 지향 데이터베이스라면 전체 행을 읽어야 하는 쿼리지만, 컬럼 지향에서는 집계에 필요한 컬럼만 읽습니다. 전 기간 스캔(1억 행)이어서 파티션 프루닝은 없었고(D 오답), quantile은 모든 입력 행을 처리하며 최대 8,192개 reservoir 표본으로 근사치를 계산합니다. 샘플링은 필요한 컬럼의 전체 입력 스캔을 없애지 않습니다. 정확한 분위수는 quantileExact 계열을 별도로 검토합니다.

  1. 이 가이드북의 판단 기준에 따를 때, ClickHouse를 관리형 서비스가 아니라 EKS에 self-hosted로 운영하는 선택이 특히 설득력을 갖는 경우는?
    • A) 전담 플랫폼 팀이 없고 데이터베이스 운영 경험이 전무할 때
    • B) 표준 관리형 서비스가 충분하고 테넌트가 하나뿐일 때
    • C) 관리형 제공이 제한적이거나 비용 배수가 크고, 플랫폼 팀이 Operator 기반 운영(백업·복구 리허설 포함)을 감당할 수 있을 때
    • D) 데이터가 100 GiB 미만으로 작을 때
정답 보기

정답: C) 관리형 제공이 제한적이거나 비용 배수가 크고, 플랫폼 팀이 Operator 기반 운영(백업·복구 리허설 포함)을 감당할 수 있을 때

설명: 이 판단 기준은 벤치마크 문서가 아니라 데이터베이스 섹션 개요의 관리형 vs 셀프호스팅 프레임워크에서 나온 것입니다. ClickHouse는 Apache-2.0 라이선스에 성숙한 커뮤니티 Operator(Altinity)가 있어 셀프호스팅이 현실적인 선택지가 됩니다 — 다만 Operator의 기능 범위와 백업·복구·업그레이드를 실제로 운영할 팀을 검증해야 합니다. 반대로 운영 인력이 부족하거나 관리형으로 충분하면 관리형이 정답입니다 — 직접 StatefulSet을 운영한다면 같은 백업·복구·업그레이드 책임을 직접 구현해야 합니다.