ClickHouse — 열 지향 분석 DB 를 속까지 · SummingMergeTree 와 AggregatingMergeTree · 퀴즈
퀴즈: 집계 엔진과 -State/-Merge
6문항. 정답과 해설은 풀어 본 뒤에 보여 드립니다.
SummingMergeTree 요약 표를 시간대별로 세 번 넣은 직후 `SELECT * FROM daily` 가 키마다 세 행을 돌려주었다. 맞는 답을 내는 조회는?
- 병합이 끝날 때까지 기다렸다가 SELECT * 로 다시 읽는다
- SELECT DISTINCT site, day, hits 로 중복 행을 없앤다
- SELECT site, day, max(hits) 로 가장 큰 조각만 고른다
- SELECT site, day, sum(hits) ... GROUP BY site, day 로 조회에서 다시 더한다
SummingMergeTree 표에 `mx UInt32` 열을 "최댓값" 으로 쓰려고 넣었는데 병합 뒤 10 과 20 이 30 이 되었다. 이유는?
- UInt32 는 병합 때 넘침을 막으려고 더해 둔다
- 더할 열을 엔진 인자로 적지 않으면 정렬 키가 아닌 모든 숫자 열을 더하기 때문이다
- SummingMergeTree 는 max 를 sum 으로 바꾸는 최적화를 한다
- 두 행의 정렬 키가 달라서 따로 더해졌다
하루의 서로 다른 사용자 수를 시간대별 세 행의 숫자(1772·1771·1779)로 저장해 두었다. 하루 전체의 사용자 수를 이 숫자들로 구할 수 없는 까닭은?
- 여러 시간대에 온 같은 사람이 각 숫자에 겹쳐 있어 더하면 중복으로 세기 때문이다
- uniqExact 결과는 UInt64 라서 더하면 넘치기 때문이다
- 숫자 세 개의 평균을 내야 하는데 개수를 모르기 때문이다
- 서로 다른 사용자 수는 병합 때 자동으로 지워지기 때문이다
AggregatingMergeTree 에 `avgState(dur_ms)` 로 넣은 상태를 `avgMerge` 로 끝낸 값이 원본 `avg(dur_ms)` 와 정확히 같았다. 이유는?
- avgMerge 는 원본 표를 다시 읽어 평균을 낸다
- 평균은 시간대가 달라도 늘 같은 값이 나오기 때문이다
- avg 의 상태는 합과 개수를 들고 있어 합친 뒤 나누면 전체 평균이 되기 때문이다
- avgMerge 는 각 행 평균의 평균을 내는데 우연히 같았다
사이트별 일일 `uniqExact` 상태 표에서 "사이트 구분 없는 일일 사용자 수" 표를 원본 없이 만들려면?
- 사이트별 uniqExactMerge 결과를 날짜로 묶어 sum() 한다
- uniqExactMergeState(users) 로 날짜별 상태를 만들어 새 AggregatingMergeTree 에 넣는다
- finalizeAggregation(users) 를 날짜로 묶어 max() 한다
- 사이트별 상태 표를 OPTIMIZE FINAL 하면 날짜 단위로 합쳐진다
원본 100만 행을 `hits = 1` 인 행 그대로 SummingMergeTree 에 INSERT 한 번으로 넣었더니 곧바로 150행이 되었다. 무엇 때문인가?
- INSERT 직후 백그라운드 병합이 반드시 끝나기 때문이다
- SummingMergeTree 는 INSERT 때 원본 표를 GROUP BY 해서 읽기 때문이다
- 행 수가 많으면 서버가 자동으로 샘플링하기 때문이다
- optimize_on_insert 가 켜져 있어 한 INSERT 블록 안의 같은 키는 넣는 순간 합쳐지기 때문이다