Every Millisecond Counts
ClickHouse 쿼리 성능을 개선하여 수 분이 걸리던 쿼리 시간을 400밀리초 수준으로 단축하는 최적화 방법을 소개합니다. 이 최적화는 대용량 데이터에서 발생하는 이벤트 처리와 `ReplacingMergeTree` 엔진의 `FINAL` 작업 효율성을 높이는 데 중점을 두었습니다.
기존에는 월별로 파티셔닝하는 방식이 사용되었으나, 이벤트 배치 처리로 인해 파티션 간의 데이터 중첩과 병합 과정에서 비효율이 발생했습니다. 이를 해결하기 위해 파티셔닝 키를 `client_customer_id % 36`으로 변경하여 데이터 분산을 개선하고 `FINAL` 작업의 병렬성을 확보했습니다. 이 전략은 데이터 파이프라인 구축 단계에서 불필요한 범위 계산을 줄여 성능을 향상시켰습니다.
또한, 이벤트 유형(`event_type`)을 정렬 키의 앞쪽에 배치하는 변경을 통해 쿼리 시 읽어야 하는 행의 수를 100배 이상 줄였습니다. 결과적으로 데이터 처리량이 996만 건에서 9만 4천 건으로 대폭 감소했으며, 쿼리 시간은 기존 85초에서 약 400밀리초로 200배 이상 개선되었습니다.
이러한 개선은 데이터가 변경된 과거 기록을 처리하는 과정에서 불필요한 데이터 읽기를 줄이고 `FINAL` 절을 적용하기 전에 필터링을 수행함으로써 달성되었습니다. 다만, 이 최적화는 특정 데이터셋에 대한 테스트를 기반으로 하며, 모든 데이터에 동일하게 적용되지는 않을 수 있다는 점을 고려해야 합니다.
기존에는 월별로 파티셔닝하는 방식이 사용되었으나, 이벤트 배치 처리로 인해 파티션 간의 데이터 중첩과 병합 과정에서 비효율이 발생했습니다. 이를 해결하기 위해 파티셔닝 키를 `client_customer_id % 36`으로 변경하여 데이터 분산을 개선하고 `FINAL` 작업의 병렬성을 확보했습니다. 이 전략은 데이터 파이프라인 구축 단계에서 불필요한 범위 계산을 줄여 성능을 향상시켰습니다.
또한, 이벤트 유형(`event_type`)을 정렬 키의 앞쪽에 배치하는 변경을 통해 쿼리 시 읽어야 하는 행의 수를 100배 이상 줄였습니다. 결과적으로 데이터 처리량이 996만 건에서 9만 4천 건으로 대폭 감소했으며, 쿼리 시간은 기존 85초에서 약 400밀리초로 200배 이상 개선되었습니다.
이러한 개선은 데이터가 변경된 과거 기록을 처리하는 과정에서 불필요한 데이터 읽기를 줄이고 `FINAL` 절을 적용하기 전에 필터링을 수행함으로써 달성되었습니다. 다만, 이 최적화는 특정 데이터셋에 대한 테스트를 기반으로 하며, 모든 데이터에 동일하게 적용되지는 않을 수 있다는 점을 고려해야 합니다.