ClickHouse — 열 지향 분석 DB 를 속까지 · 타입과 코덱 · 실습
같은 값을 타입과 코덱만 바꿔 담아 크기를 잰다
목표
기본 타입·기본 코덱의 표와, 같은 값을 타입이나 코덱만 바꿔 담은 비교대 표를 만들어 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.json 에 plain_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 에 적으세요.
참고
- 서버는 파드가 뜰 때 이미 떠 있습니다.
clickhouse-client만 치면 붙습니다. 멈췄다면ch-up. - 열별 크기:
SELECT name, data_compressed_bytes, data_uncompressed_bytes FROM system.columns WHERE database = 'codecs' AND table = '...'. 코덱은 같은 표의compression_codec열에 보입니다(기본 코덱이면 빈 문자열). - 숫자를 JSON 에 따옴표 없이 받으려면
--output_format_json_quote_64bit_integers 0. JSONEachRow 한 줄을 그대로 파일로 저장해도 됩니다. - 크기를 재기 전에 늘
OPTIMIZE TABLE ... FINAL. 파트가 여럿이면 압축 블록 경계가 달라 숫자가 흔들리고, 채점기는 파트가 하나일 때만 받습니다(실습용 절차입니다 — 운영에서는 병합을 서버에 맡깁니다). - 흔한 실수: 비교대 표에 plain 을 두 번 넣는 것(200만 행). 그때는
TRUNCATE TABLE뒤 다시 넣습니다. 전문 코덱만 적고 범용 코덱을 빼면(CODEC(Delta)) 서버가 거절하거나 크기가 잘 줄지 않습니다. - 공식 문서: [CODEC](https://clickhouse.com/docs/reference/statements/create/table/codec) · [Compression in ClickHouse](https://clickhouse.com/docs/guides/clickhouse/data-modelling/compression/compression-in-clickhouse) · [LowCardinality](https://clickhouse.com/docs/reference/data-types/lowcardinality) · [system.columns](https://clickhouse.com/docs/reference/system-tables/columns)
8단계
- 아무 생각 없이 만든 표
- 100만 행을 넣고 파트를 하나로
- String · LowCardinality · Enum8
- 시각 열 — LZ4 · ZSTD · Delta · DoubleDelta
- 전문 코덱이 늘 이기지는 않는다
- Nullable 은 파일을 하나 더 둔다
- 이긴 선택을 모은 표
- 운영 표의 코덱을 바꾸면 언제 작아지나