LabHub
学习 学习路径 课程

ClickHouse — 열 지향 분석 DB 를 속까지 · 구체화 뷰는 INSERT 트리거 · 实验

구체화 뷰가 본 것과 못 본 것

在 LabHub 中继续学习

목표

원천 표에 구체화 뷰를 걸어 INSERT 가 대상 표로 흐르는 것을 확인하고, 뷰가 보지 못하는 세 가지 — 뷰 이전의 행, 병합 전의 중복 키, JOIN 오른쪽 표의 변화 — 를 숫자로 재현한다.

왜 중요한가

ClickHouse 의 구체화 뷰는 "저장된 쿼리" 가 아니라 INSERT 트리거입니다. 그래서 되채우기를 빠뜨리면 과거가 비고, 두 번 되채우면 두 배가 되고, 대상 표를 더하지 않고 읽으면 병합 시점에 따라 숫자가 흔들리고, 차원 표 조인은 늦게 온 차원을 영영 놓칩니다. 이 실습의 채점기는 여러분이 적은 숫자를 믿지 않습니다 — 대상 표를 원천 표(또는 픽스처 생성 식)로 다시 계산한 값과 칸마다 대조하고, 저장한 SELECT 는 읽기 전용으로 다시 돌려 결과와 읽은 행 수를 잽니다.

단계

1. 데이터베이스 mv 와 표 mv.orders 를 만드세요 — 열 order_id UInt64, ts DateTime, shop LowCardinality(String), product_id UInt32, user_id UInt32, qty UInt32, price UInt32 (이 순서), 엔진 MergeTree, ORDER BY (shop, ts). 그리고 /opt/lab/fixtures/mv/orders_1.sql(9월 1–15일, 20만 건)을 한 번 넣으세요.
2. 대상 표 mv.daily_sales (day Date, shop LowCardinality(String), orders UInt64, revenue UInt64)SummingMergeTree, ORDER BY (shop, day) 로 만들고, 구체화 뷰 mv.daily_sales_mvTO mv.daily_sales 로 만드세요 — toDate(ts) AS day, shop, count() AS orders, sum(qty * price) AS revenueGROUP BY day, shop.
3. /opt/lab/fixtures/mv/orders_2.sql(9월 16–30일, 20만 건)을 넣은 직후, mv.orders 의 행 수를 source_orders, mv.daily_salessum(orders)view_orders/root/ch/mv/gap.json 에 적으세요.
4. 뷰가 보지 못한 1차분을 mv.daily_sales 에 되채워, 대상 표가 원천 전체를 (shop, day) 별로 정확히 담게 하세요. 2차분을 또 넣으면 안 됩니다.
5. mv.daily_sales 에서 shop-3 의 날짜별 주문 수·매출을 구하는 /root/ch/mv/q_daily.sql 을 쓰세요 — 열 day, orders, revenue, 날짜순. 병합 전에도 맞도록 더해서 읽어야 합니다.
6. 대상 표 mv.shop_stats (shop LowCardinality(String), day Date, orders AggregateFunction(count), buyers AggregateFunction(uniqExact, UInt32))AggregatingMergeTree, ORDER BY (shop, day) 로, 뷰 mv.shop_stats_mvTO mv.shop_stats 로(countState()·uniqExactState(user_id)) 만들고 이미 있는 원천을 한 번 되채우세요. 그리고 상점별 한 달 고유 구매자를 mv.shop_stats 에서 구하는 /root/ch/mv/q_buyers.sql 을 쓰세요 — 열 shop, buyers, 상점순.
7. mv.orders 와 같은 열에 status LowCardinality(String) 을 끝에 더한 mv.rawENGINE = Null 로 만들고, status = 'paid' 인 행만 mv.orders 로 보내는 뷰 mv.raw_mv 를 만든 뒤 /opt/lab/fixtures/mv/raw.sql한 번 넣으세요.
8. mv.products (product_id UInt32, category LowCardinality(String))(MergeTree, ORDER BY product_id)와 mv.cat_sales (category LowCardinality(String), orders UInt64)(SummingMergeTree, ORDER BY category), 그리고 mv.ordersmv.productsINNER JOIN 해 범주별 count() 를 보내는 뷰 mv.cat_sales_mv 를 만드세요. 그다음 products.sqllate.sqlproducts_new.sql (모두 /opt/lab/fixtures/mv/) 순서로 넣고, 늦은 주문 수(order_id >= 2000000)를 late_orders, mv.cat_salessum(orders)joined_orders, 그 차이를 lost_orders/root/ch/mv/join.json 에 적으세요.

참고

8个步骤

  1. 원천 표를 만들고 1차분을 넣는다
  2. 대상 표와 구체화 뷰를 만든다
  3. 뷰가 본 것과 원천을 비교한다
  4. 빠진 구간만 되채운다
  5. 병합 전에도 맞게 대상 표를 읽는다
  6. 더할 수 없는 값은 상태로 담는다
  7. Null 표에서 시작하는 연쇄 뷰
  8. JOIN 뷰는 오른쪽 표의 변화를 모른다