MySQL 마이그레이션시 Point Query 성능 극대화
🖊️

MySQL 마이그레이션시 Point Query 성능 극대화

ClickHouse 분류
Case Study
Type
Research
작성자

Ken

MySQL 워크로드를 ClickHouse로 전환할 때 가장 많이 받는 질문이 있습니다.

"분석 쿼리가 빠른 건 알겠는데, Point Query는 어떤가요?"

이전 글에서 ClickHouse의 MySQL Interface를 통해 기존 MySQL 클라이언트와 애플리케이션을 그대로 사용할 수 있다는 점을 다뤘습니다. 그리고 분석 쿼리에서 ClickHouse가 MySQL보다 월등히 빠르다는 것은 이미 널리 알려진 사실입니다.

그렇다면 남은 질문은 하나입니다: Point Query는 어떨까요?

이번 글에서는 Point Query 성능을 MySQL 수준으로 끌어올리는 방법을 실제 벤치마크와 함께 살펴보겠습니다.

  • 테스트 시나리오: 게임 서버의 플레이어 조회
  • Baseline: 아무 최적화 없이 시작하기
  • 테이블 스키마
  • Baseline 성능 결과
  • 왜 ClickHouse의 Point Query가 MySQL보다 느린가?
  • 최적화 전략 1: Index Granularity 조정
  • ClickHouse Cloud에서 지원 여부 확인
  • 최적화된 스키마
  • 효과 분석
  • 최적화 전략 2: Bloom Filter Index
  • 최적화 전략 3: PREWHERE 활용
  • 최종 벤치마크 결과
  • QPS 비교
  • 레이턴시 비교 (P50)
  • 성능 요약
  • 최적화 Trade-off 정리
  • 더 높은 성능이 필요하다면: Dictionary 엔진
  • 결론: ClickHouse로 Point Query를 처리해도 될까?
  • 핵심 포인트
  • 참고 자료

테스트 시나리오: 게임 서버의 플레이어 조회

실제 고객 문의를 바탕으로 테스트를 설계했습니다.

유즈케이스: 게임 앱에서 플레이어의 마지막 접속 정보를 조회

  • 데이터 규모: 200만 유저
  • 쿼리 패턴: WHERE player_id = ? (Primary Key 기반 단일 row 조회)
  • 요구사항: 낮은 레이턴시, 높은 동시성 지원

핵심 질문은 이것입니다: 컬럼 스토어인 ClickHouse가 row 단위 조회에서 얼마나 효율적일 수 있는가?

Baseline: 아무 최적화 없이 시작하기

먼저 기본 설정으로 MySQL과 ClickHouse를 비교했습니다.

테이블 스키마

Baseline 성능 결과

지표
MySQL
ClickHouse (기본)
비율
평균 QPS
4,687
3,070
65%
P50 레이턴시
0.65ms
2.10ms
3.2배
P95 레이턴시
1.81ms
3.80ms
2.1배

MySQL 대비 65% 수준입니다. 나쁘지 않지만, 개선의 여지가 있습니다.

왜 ClickHouse의 Point Query가 MySQL보다 느린가?

성능 차이를 이해하려면 두 데이터베이스의 인덱스 구조를 비교해야 합니다.

MySQL B-Tree: O(log n) 복잡도로 정확한 row 위치를 찾습니다.

ClickHouse Sparse Index: 모든 row가 아닌 granule 단위(기본 8,192 rows)로만 인덱스를 저장합니다. 200만 rows는 약 244개 granule로 나뉘고, Point Query 시 해당 granule을 찾은 후 내부에서 추가 스캔이 필요합니다.

이것이 근본적인 성능 차이의 원인입니다. 하지만 ClickHouse는 이를 보완할 수 있는 여러 최적화 옵션을 제공합니다.

최적화 전략 1: Index Granularity 조정

가장 효과적인 최적화는 index_granularity를 줄이는 것입니다.

ClickHouse Cloud에서 지원 여부 확인

먼저 ClickHouse Cloud에서 이 설정을 변경할 수 있는지 직접 테스트했습니다.

-- ClickHouse Cloud에서 테스트
CREATE TABLE test_granularity_256 (
    id UInt64,
    name String
) ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 256;

-- 결과: 성공! 테이블 생성 완료

결론: ClickHouse Cloud에서 index_granularity 축소가 완전히 지원됩니다.

최적화된 스키마

CREATE TABLE player_last_login_optimized
(
    player_id UInt64,
    player_name String,
    -- ... 기타 컬럼 ...

    -- Bloom Filter Index 추가
    INDEX idx_player_id_bloom player_id TYPE bloom_filter(0.01) GRANULARITY 1
)
ENGINE = MergeTree()
ORDER BY player_id
SETTINGS
    index_granularity = 256;  -- 8192 → 256 (32배 축소)

효과 분석

설정
Granule 수
Point Query 시 최대 스캔
인덱스 크기
8,192 (기본)
244
8,192 rows
~2KB
256 (최적화)
7,813
256 rows
~62KB

Granule 크기를 32배 줄이면, Point Query 시 스캔해야 할 최대 row 수도 32배 감소합니다.

최적화 전략 2: Bloom Filter Index

Bloom Filter는 "이 granule에 해당 값이 확실히 없다"를 빠르게 판단하는 확률적 자료구조입니다.

INDEX idx_player_id_bloom player_id TYPE bloom_filter(0.01) GRANULARITY 1
  • False Positive Rate 0.01: 1% 확률로 "있을 수도 있다"고 잘못 판단
  • GRANULARITY 1: 각 granule마다 별도 Bloom Filter 생성

Primary Key에 이미 Sparse Index가 있지만, Bloom Filter는 추가적인 필터링 레이어로 작동합니다.

최적화 전략 3: PREWHERE 활용

ClickHouse는 WHERE 대신 PREWHERE를 사용하면 필터 컬럼만 먼저 읽어 필터링한 후, 매칭되는 row의 나머지 컬럼을 읽습니다.

-- 기본
SELECT * FROM player_last_login WHERE player_id = 12345;

-- 최적화
SELECT * FROM player_last_login PREWHERE player_id = 12345;

테스트 결과: 동시성 16 이상에서 3~8% 성능 향상

최종 벤치마크 결과

모든 최적화를 적용한 결과입니다.

QPS 비교

동시성
MySQL
CH 기본
CH 최적화
최적화 효과
8
4,698
3,183
3,418
+7.4%
16
4,547
2,972
3,281
+10.4%
24
4,646
3,104
3,159
+1.8%
32
4,860
3,022
3,142
+4.0%

레이턴시 비교 (P50)

동시성
MySQL
CH 기본
CH 최적화
개선율
8
0.70ms
2.10ms
1.89ms
-10%
16
0.81ms
2.74ms
2.58ms
-6%
24
0.91ms
3.83ms
3.53ms
-8%
32
1.08ms
5.29ms
4.47ms
-15%

성능 요약

구성
평균 QPS
MySQL 대비
적용 최적화
MySQL
4,687
100%
-
ClickHouse 최적화
3,250
69%
granularity=256 + PREWHERE
ClickHouse 기본
3,070
65%
없음

최적화 Trade-off 정리

최적화
성능 향상
비용
권장 여부
index_granularity=256
+5~11%
인덱스 +60KB
✅ 강력 추천
Bloom Filter Index
+2~3%
저장 공간 미미
✅ 추천
PREWHERE (동시성 16+)
+3~8%
없음
✅ 추천
PREWHERE (동시성 8 이하)
-1~2%
-
❌ 비추천

더 높은 성능이 필요하다면: Dictionary 엔진

Point Query 성능을 MySQL과 동등하거나 그 이상으로 끌어올리려면 Dictionary 엔진을 고려할 수 있습니다.

예상 성능: MergeTree 대비 2~3배 향상 (10,000+ QPS)

Trade-off:

  • ✅ 메모리 내 해시테이블로 O(1) 조회
  • ❌ 메모리 사용량 증가 (200만 rows ≈ 1GB)
  • ❌ 실시간 업데이트 불가 (주기적 새로고침)

결론: ClickHouse로 Point Query를 처리해도 될까?

답은 "Yes, 충분히 실용적"입니다.

핵심 포인트

  1. ClickHouse 기본 설정으로도 MySQL 대비 65% 성능 - 대부분의 앱 API 요구사항(< 100ms)을 충족
  2. 최적화 적용 시 69~73%까지 향상 - index_granularity=256 + PREWHERE 조합
  3. P50 레이턴시 2~5ms - 실시간 게임 서버에서도 충분히 사용 가능한 수준
  4. 분석 쿼리는 ClickHouse가 압도적으로 빠름 - 이미 검증된 사실이므로, Point Query만 해결하면 완전한 전환이 가능

MySQL에서 ClickHouse로 전환을 고려하고 있다면, Point Query 성능은 더 이상 장벽이 아닙니다. 분석 쿼리에서의 압도적인 성능 + Point Query에서의 실용적인 성능을 갖춘 ClickHouse는 OLTP와 OLAP 워크로드를 모두 처리할 수 있는 강력한 선택지입니다.

참고 자료

  • ClickHouse Primary Indexes 가이드
  • Altinity: Maximum QPS for key-value lookups
  • ClickHouse Skipping Indices