- ClickHouse가 새로운 최적화 기법인 lazy materialization을 도입하여
Top N쿼리 성능을 최대 1,500배까지 향상시킴 - 필요할 때만 컬럼 데이터를 읽는 전략을 통해 디스크 I/O를 최소화함
- 기존의 컬럼 스토리지, 인덱스, PREWHERE 기법과 함께 계층적 I/O 최적화 스택을 구성
- 쿼리 실행 계획에 따라 컬럼 데이터를 지연 로딩하여, 특히 LIMIT 절이 있는 쿼리에서 큰 효과를 발휘함
- 기본 설정으로 활성화됨으로써, 코드 변경 없이 성능 향상을 얻을 수 있음
ClickHouse의 지연된 최적화 전략: Lazy Materialization
핵심 개념
- ClickHouse는 불필요한 데이터를 읽지 않음으로써 성능을 극대화함
- lazy materialization은 쿼리 실행 중 실제로 필요한 시점에만 컬럼 데이터를 로딩하는 방식
- 기존의 I/O 최적화 기법들과 독립적으로 작동하면서 상호 보완적인 성능 향상을 제공함
기존 I/O 최적화 기술
- 컬럼 기반 저장소: 필요한 컬럼만 읽음
- Sparse Index / Skipping Index / Projections: 필터링된 조건에 맞는 granule만 읽음
- PREWHERE: 비인덱스 컬럼을 조기 필터링
- Query Condition Cache: 반복 쿼리의 결과를 캐시해 동일 granule 재처리를 피함
Lazy Materialization의 원리
- 기존 기술이 필터링을 통한 I/O 감소에 집중했다면, lazy materialization은 연산 시점까지 읽기를 연기함
- 쿼리의 다음 단계가 필요한 컬럼만 즉시 읽고, 나머지는 LIMIT 이후에 필요할 때 읽음
- 특히 Top N 쿼리에서 일부 컬럼만 조회되므로, 대용량 텍스트 컬럼 등을 거의 읽지 않음
컬럼 독립 저장 방식이기 때문에 가능한 최적화이며, row-based DB에선 불가능한 접근
실제 예시: Amazon 리뷰 데이터셋
-
150M rows, 70GB 비압축, 30GB 압축
-
Top N 쿼리 예시:
SELECT helpful_votes FROM amazon.amazon_reviews ORDER BY helpful_votes DESC LIMIT 3;- 실행 시간: 0.07초
- 컬럼 단독 조회로 고속 처리
-
대용량 텍스트 컬럼 조회 예시:
SELECT review_body FROM amazon.amazon_reviews FORMAT Null;- 실행 시간: 176초
- 단일 컬럼이지만 56GB로 디스크 I/O 병목 발생
최적화 계층 적용별 성능 비교
1. 최적화 없음 (Baseline)
- 실행 시간: 219초
- 처리량: 72GB, 150M rows
- 모든 컬럼을 모두 읽고 정렬
2. Primary Key Index 적용
- 실행 시간: 96초
- 처리량: 28GB, 53M rows
- PK 기반 granule 필터링으로 50% 이상 시간 절감
3. PREWHERE 추가
- 실행 시간: 61초
- 처리량: 16GB
- 비인덱스 필터 조건도 적용하여 추가 I/O 감소
4. Lazy Materialization 활성화
- 실행 시간: 0.18초
- 처리량: 807MB
- 최종적으로 필요한 3개 row만 큰 컬럼에서 로딩
총 1,200배 이상 성능 향상, 150배 이상 메모리 사용 감소
필터 없는 Top N 쿼리에도 유효
-
필터 없는 전체 정렬 쿼리에서:
SELECT helpful_votes, product_title, review_headline, review_body FROM amazon.amazon_reviews ORDER BY helpful_votes DESC LIMIT 3; -
lazy materialization 전: 219초
-
lazy materialization 후: 0.139초
-
1,576배 속도 향상, 40배 I/O 감소, 300배 메모리 사용 감소
실행 계획 확인
EXPLAIN actions = 1
SELECT helpful_votes, product_title, review_headline, review_body
FROM amazon.amazon_reviews
ORDER BY helpful_votes DESC
LIMIT 3
SETTINGS query_plan_optimize_lazy_materialization = true;
- 결과:
Lazily read columns: review_headline, review_body, product_title
Limit
Sorting
ReadFromMergeTree
- 정렬과 LIMIT 후에만 대용량 컬럼을 로딩
결론
- ClickHouse의 I/O 최적화 스택 완성: Index → PREWHERE → Lazy Materialization
- 코드 변경 없이, 쿼리 실행 방식만으로 성능 수백~수천 배 향상
- 특히 Top N 패턴, 대용량 컬럼, LIMIT 쿼리에 이상적
- 기본 설정으로 활성화되어 사용자가 따로 설정하지 않아도 자동 적용
같은 SQL, 같은 머신, 다른 결과
빠름 = 덜 읽음 = ClickHouse