LabHub
배우기 러닝패스 코스

ClickHouse — 열 지향 분석 DB 를 속까지 · 타입과 코덱 · 실습

같은 값을 타입과 코덱만 바꿔 담아 크기를 잰다

LabHub 에서 이어서 보기

목표

기본 타입·기본 코덱의 표와, 같은 값을 타입이나 코덱만 바꿔 담은 비교대 표를 만들어 system.columns 의 압축 후 바이트로 어느 선택이 이기는지 확인합니다. 마지막에 운영 중인 표의 코덱을 바꾸면 크기가 언제 바뀌는지 봅니다.

왜 중요한가

분석 DB 의 디스크·메모리·읽기 비용은 결국 바이트입니다. 같은 자료라도 타입과 코덱에 따라 크기가 몇 배씩 달라지는데, 어느 코덱이 이기는지는 자료의 모양이 정합니다 — 이 실습에서도 전문 코덱 하나는 오히려 손해를 봅니다. 그래서 비교는 늘 같은 자료·같은 정렬에서 한 가지만 바꿔 해야 합니다. 이 실습의 비교대 표가 그 방법입니다. 채점기는 여러분이 적은 숫자를 믿지 않고 system.columns 를 직접 읽어 대조하며, 판정은 속도가 아니라 바이트로 합니다.

단계

1. 데이터베이스 codecs 와 표 codecs.plain 을 만드세요 — 열 ts DateTime, host String, status String, cpu Float64, bytes_total UInt64, latency_ms UInt32, err_code Nullable(UInt16)(이 순서, 코덱 없이), 엔진 MergeTree, ORDER BY (host, ts).
2. /opt/lab/fixtures/codecs/metrics.sql한 번 실행해 100만 행을 넣고 OPTIMIZE TABLE codecs.plain FINAL 로 파트를 하나로 만드세요.
3. 표 codecs.status_bench (host String, ts DateTime, s_str String, s_lc LowCardinality(String), s_enum Enum8('ok' = 1, 'warn' = 2, 'error' = 3, 'timeout' = 4))ORDER BY (host, ts) 로 만들어 세 열 모두에 plain 의 status 를 넣고, 파트를 하나로 합친 뒤 세 열의 압축 후 바이트와 가장 작은 열 이름(smallest)을 /root/ch/codecs/types.json 에 적으세요.
4. 표 codecs.ts_bench (host String, ts DateTime, ts_zstd DateTime CODEC(ZSTD(1)), ts_delta DateTime CODEC(Delta, ZSTD(1)), ts_dd DateTime CODEC(DoubleDelta, ZSTD(1)))ORDER BY (host, ts) 로 만들어 네 시각 열 모두에 plain 의 ts 를 넣고, 파트를 하나로 합친 뒤 네 열의 압축 후 바이트와 가장 작은 열(best)을 /root/ch/codecs/time.json 에 적으세요.
5. 표 codecs.num_bench (host String, ts DateTime, cnt UInt64 CODEC(ZSTD(1)), cnt_delta UInt64 CODEC(Delta, ZSTD(1)), lat UInt32 CODEC(ZSTD(1)), lat_t64 UInt32 CODEC(T64, ZSTD(1)), cpu Float64 CODEC(ZSTD(1)), cpu_gorilla Float64 CODEC(Gorilla, ZSTD(1)))ORDER BY (host, ts) 로 만들어 짝마다 plain 의 bytes_total·latency_ms·cpu 를 넣고, 파트를 하나로 합친 뒤 여섯 열의 압축 후 바이트와, 짝보다 오히려 커진 전문 코덱 열 이름의 배열(codec_lost)을 /root/ch/codecs/numbers.json 에 적으세요.
6. 표 codecs.null_bench (host String, ts DateTime, err_null Nullable(UInt16), err_zero UInt16)ORDER BY (host, ts) 로 만들어 err_null 에는 plain 의 err_code 를, err_zero 에는 NULL 을 0 으로 채운 값을 넣고 파트를 하나로 합치세요. NULL 인 행을 세는 /root/ch/codecs/q_isnull.sql 을 만들고, null_uncompressed(err_null 의 압축 전 바이트)·isnull_bytes_read(q_isnull.sql 의 bytes_read)·avg_null·avg_zero(두 열의 avg) 를 /root/ch/codecs/nullable.json 에 적으세요.
7. 표 codecs.tuned (ts DateTime CODEC(Delta, ZSTD(1)), host LowCardinality(String), status LowCardinality(String), cpu Float64 CODEC(ZSTD(1)), bytes_total UInt64 CODEC(Delta, ZSTD(1)), latency_ms UInt16 CODEC(T64, ZSTD(1)), err_code UInt16)ORDER BY (host, ts) 로 만들어 plain 의 행을 옮기고(NULL 은 0) 파트를 하나로 합친 뒤, 두 표의 압축 후 바이트 합을 /root/ch/codecs/tuned.jsonplain_total·tuned_total 로 적으세요.
8. codecs.legacy 를 plain 과 같은 열·엔진으로 만들어 plain 의 행을 넣고 파트를 하나로 합친 뒤, ts 의 압축 후 바이트를 잽니다(before). ALTER TABLE codecs.legacy MODIFY COLUMN ts CODEC(Delta, ZSTD(1)) 직후에 다시 재고(after_alter), OPTIMIZE TABLE codecs.legacy FINAL 뒤에 또 재서(after_optimize) 세 값을 /root/ch/codecs/alter.json 에 적으세요.

참고

8단계

  1. 아무 생각 없이 만든 표
  2. 100만 행을 넣고 파트를 하나로
  3. String · LowCardinality · Enum8
  4. 시각 열 — LZ4 · ZSTD · Delta · DoubleDelta
  5. 전문 코덱이 늘 이기지는 않는다
  6. Nullable 은 파일을 하나 더 둔다
  7. 이긴 선택을 모은 표
  8. 운영 표의 코덱을 바꾸면 언제 작아지나