LLM WikiAccess-protected knowledge portal
← 스터디 홈
6편 · 약 13분

운영과 모니터링

모니터링의 구조

ClickHouse는 운영 상태 대부분을 system 데이터베이스의 시스템 테이블로 노출한다. 외부 모니터링 도구 없이도 SQL로 진단할 수 있다는 것이 장점이다.

쿼리 레이어 system.query_log system.processes
스토리지 레이어 system.parts system.merges system.part_log
복제 레이어 system.replication_queue system.replicas
서버 레이어 system.metrics system.events system.asynchronous_metrics
Prometheus exporter / Grafana 대시보드로 시각화 가능
ClickHouse 모니터링 계층

핵심 시스템 테이블 요약

테이블내용주요 용도
system.query_log완료·실패한 쿼리 이력슬로우 쿼리, 오류 분석
system.processes현재 실행 중인 쿼리장시간 쿼리 탐지, KILL 대상 식별
system.parts테이블별 파트 목록파트 수 모니터링, 파티션 상태
system.merges진행 중인 백그라운드 병합병합 속도, 적체 진단
system.replicas복제 테이블 상태복제 지연, 큐 깊이
system.replication_queue복제 대기 작업 목록복제 오류 원인 파악
system.metrics현재 순간 카운터커넥션 수, 스레드 수
system.events누적 이벤트 카운터SELECT·INSERT 횟수 추세
system.asynchronous_metrics백그라운드 수집 지표메모리·CPU 시계열

쿼리 성능 진단

슬로우 쿼리 찾기

SELECT
    left(query, 100)        AS query_snippet,
    query_duration_ms,
    read_rows,
    formatReadableSize(read_bytes) AS read_size,
    memory_usage
FROM system.query_log
WHERE type = 'QueryFinish'
  AND query_duration_ms > 2000
  AND event_date = today()
ORDER BY query_duration_ms DESC
LIMIT 20;
  • read_bytes가 크고 result_rows가 작으면 인덱스 효율이 낮다.
  • memory_usage가 높으면 집계·정렬 중간 상태가 메모리에 많이 올라간 것.

현재 실행 중인 장시간 쿼리

SELECT
    query_id,
    elapsed,
    read_rows,
    left(query, 80) AS query_snippet
FROM system.processes
WHERE elapsed > 30
ORDER BY elapsed DESC;

-- 필요 시 강제 종료
KILL QUERY WHERE query_id = '<id>';

오류 빈도 추적

SELECT
    toStartOfHour(event_time) AS hour,
    count() AS error_count,
    groupArray(10)(exception) AS sample_exceptions
FROM system.query_log
WHERE type = 'ExceptionWhileProcessing'
  AND event_date >= today() - 1
GROUP BY hour
ORDER BY hour;

Parts 관리 — "Too Many Parts" 문제

ClickHouse에서 가장 자주 만나는 운영 문제 중 하나다.

원인

INSERT가 들어올 때마다 새 파트가 생긴다. 백그라운드 병합이 소규모 삽입 속도를 따라잡지 못하면 파트 수가 계속 늘어난다.

파트 수가 임계값을 초과하면 ClickHouse가 삽입을 지연(delay)하거나 예외(throw)를 던진다.

  • ClickHouse 23.6 이전: delay 150, throw 300
  • ClickHouse 23.6 이후: throw 기본값 3,000으로 상향

진단

SELECT
    database,
    table,
    partition,
    count() AS active_parts
FROM system.parts
WHERE active
GROUP BY database, table, partition
HAVING active_parts > 100
ORDER BY active_parts DESC;

100개 미만: 정상, 100~300개: 경고, 300개 초과: 즉시 조치.

해결 방법

  1. 삽입 배치 크기 키우기 — 가장 근본적인 해결책. 행 수천~수만 건을 묶어 한 번에 INSERT한다.
  2. async_insert 활성화 — 클라이언트가 작은 삽입을 보낼 수밖에 없을 때 서버 측 버퍼링으로 배치를 합친다.
SET async_insert = 1;
SET wait_for_async_insert = 1;
  1. 병합 스레드 수 늘리기
<!-- config.xml -->
<background_pool_size>16</background_pool_size>

병합 진행 모니터링

SELECT
    table,
    round(progress * 100, 1) AS progress_pct,
    elapsed,
    formatReadableSize(total_size_bytes_compressed) AS merge_size
FROM system.merges
ORDER BY elapsed DESC;

병합이 오래 걸리는 테이블이 보이면 그 테이블의 삽입 패턴을 점검한다.

복제 모니터링

ReplicatedMergeTree 계열을 쓰는 경우 복제 지연이 핵심 지표다.

-- 복제 지연 및 큐 상태
SELECT
    database,
    table,
    is_leader,
    queue_size,
    inserts_in_queue,
    merges_in_queue,
    last_queue_update_exception
FROM system.replicas
WHERE queue_size > 0
ORDER BY queue_size DESC;
  • queue_size > 0이고 계속 증가하면 복제 적체.
  • last_queue_update_exception에 오류가 있으면 복제가 멈춘 것.
-- 복제 큐에서 오류 항목만
SELECT
    table,
    type,
    last_exception,
    num_tries,
    create_time
FROM system.replication_queue
WHERE last_exception != ''
ORDER BY create_time DESC;

메모리와 디스크 관리

메모리 현황

SELECT
    metric,
    formatReadableSize(value) AS val
FROM system.asynchronous_metrics
WHERE metric IN (
    'MemoryResident',
    'MemoryVirtual',
    'MarkCacheBytes',
    'UncompressedCacheBytes'
)
ORDER BY metric;
  • MarkCacheBytes: 스파스 인덱스 마크 캐시 — 부족하면 매 쿼리마다 마크 파일을 디스크에서 읽는다.
  • UncompressedCacheBytes: 압축 해제된 데이터 블록 캐시.

디스크 파티션별 사용량

SELECT
    name,
    path,
    formatReadableSize(free_space)  AS free,
    formatReadableSize(total_space) AS total,
    round((1 - free_space / total_space) * 100, 1) AS used_pct
FROM system.disks;

TTL 만료 파티션 즉시 정리

-- TTL 정리를 강제 트리거 (기본은 백그라운드에서 자동 실행)
ALTER TABLE events MATERIALIZE TTL;

Prometheus + Grafana 연동

ClickHouse는 내장 Prometheus 엔드포인트를 제공한다.

<!-- config.xml -->
<prometheus>
    <endpoint>/metrics</endpoint>
    <port>9363</port>
    <metrics>true</metrics>
    <events>true</events>
    <asynchronous_metrics>true</asynchronous_metrics>
</prometheus>

이 엔드포인트를 Prometheus가 스크랩하고, Grafana의 ClickHouse 공식 대시보드(ID 14192)로 시각화한다. 주요 패널:

  • 쿼리 처리량 (queries/s)
  • 삽입 처리량 (rows/s)
  • 파트 수 추이
  • 병합 큐 길이
  • 복제 지연

운영 알림 임계값 권고

지표경고위험
파티션당 활성 파트 수> 100> 300
병합 큐 깊이 (merges_in_queue)> 50> 200
복제 큐 깊이 (queue_size)> 100> 500
쿼리 오류율 (1분)> 1%> 5%
p99 쿼리 지연> 5s> 30s
디스크 사용률> 70%> 85%

운영 체크리스트

① query_log → 슬로우 쿼리·오류 확인 ② system.parts → 파트 수 이상 파티션 확인 ③ system.merges → 장시간 병합·적체 여부 ④ system.replicas → 복제 지연·오류 여부 ⑤ system.disks → 디스크 여유 공간 이상 없음 → 완료 / 이상 있음 → EXPLAIN·KILL·설정 조정
일상 운영 점검 흐름
  1. 슬로우 쿼리: system.query_log에서 query_duration_ms 높은 쿼리 → EXPLAIN indexes=1 분석.
  2. 파트 폭증: system.parts active_parts > 100 → 삽입 배치 크기 점검, async_insert 고려.
  3. 병합 적체: system.merges elapsed 높은 항목 → background_pool_size 확인.
  4. 복제 오류: system.replicas.last_queue_update_exception 존재 → ZooKeeper/ClickHouse Keeper 상태 점검.
  5. 디스크 부족: system.disks 85% 초과 → TTL MATERIALIZE 또는 파티션 DROP.

한 줄 정리

ClickHouse 운영의 핵심 지표는 파트 수, 병합 큐, 복제 지연, 슬로우 쿼리 네 가지이며, 이 모두를 system.* 테이블에 직접 SQL로 질의하거나 Prometheus 엔드포인트로 수집해 Grafana에서 추적할 수 있다.

References

  • https://clickhouse.com/docs/en/operations/system-tables/query_log
  • https://clickhouse.com/docs/en/operations/system-tables/merges
  • https://clickhouse.com/docs/en/operations/system-tables/parts
  • https://clickhouse.com/docs/en/operations/system-tables/replicas
  • https://clickhouse.com/docs/tips-and-tricks/too-many-parts
  • https://chistadata.com/essential-clickhouse-metrics/
  • https://severalnines.com/blog/clickhouse-monitoring-and-observability-decision-points/
  • https://pulse.support/kb/clickhouse-system-tables
  • https://clickhouse.com/blog/clickhouse-2025-roundup