본문 바로가기
대외활동/DateEngineering Zoom Camp

[DE-Zoomcamp] 3. Data Warehouse: BigQuery로 OLAP 분석하기 (Partitioning/Clustering/Best Practice/BQML)

by 드인 2026. 2. 9.
이 글은 Data Engineering Zoomcamp의 Module 3: Data Warehouse and BigQuery 를 바탕으로
데이터 웨어하우스/BigQuery의 기본 개념부터 비용 모델(스캔 바이트)과 성능 최적화(파티셔닝·클러스터링), 그리고 이와 관련된 테이블 설계 및 실습 예시를 정리한 글입니다.

 

 

목차

  1. OLTP vs OLAP: 데이터 웨어하우스가 필요한 이유
  2. Data Warehouse와 BigQuery 포지셔닝
  3. BigQuery 비용 모델(온디맨드 vs 플랫레이트)
  4. Partitioning(파티셔닝)
  5. Clustering(클러스터링) + 자동 리클러스터링
  6. Partitioning vs Clustering 선택 가이드
  7. BigQuery Best Practices (비용/성능)
  8. BigQuery Internals (왜 컬럼형이 유리한가)
  9. (실습 코드) External Table → Partition/Cluster 테이블로 최적화하기
  10. 참고자료/출처

 

1. OLTP vs OLAP: 데이터 웨어하우스가 필요한 이유

https://docs.google.com/presentation/d/1a3ZoBAXFk8-EhUsd7rAZd-5p_HpltkzSeujjRGB2TAI/edit?slide=id.g10eebc44ce4_0_19#slide=id.g10eebc44ce4_0_19

 

운영계(OLTP)와 분석계(OLAP)는 목적이 다릅니다.

    • OLTP: 실시간 트랜잭션 처리(짧고 빠른 업데이트, 정규화 위주)
    • OLAP: 의사결정/분석/인사이트 탐색(배치 기반 갱신, 비정규화/대용량 집계)

 

2. Data Warehouse와 BigQuery 포지셔닝

슬라이드 정의 그대로, 데이터 웨어하우스는 OLAP 솔루션이며 리포팅/분석을 위한 저장소입니다.

 

BigQuery는 서버리스 데이터 웨어하우스로,

  • 서버/DB 소프트웨어 운영 없이 사용
  • 확장성/HA 같은 인프라까지 포함
  • ML/지리공간/BI 같은 기능을 내장
  • Compute(쿼리 엔진)와 Storage를 분리해 유연성을 극대화

하는 역할을 수행할 수 있습니다.

 

3. BigQuery 비용 모델(온디맨드 vs 플랫레이트)

BigQuery는 “얼마나 저장했는가”도 있지만, 실무 체감은 보통 쿼리에서 스캔한 데이터량이 비용을 좌우합니다.

    • On-demand: 처리한 데이터 1TB당 $5
    • Flat-rate(슬롯 구매): 슬롯 수 기반. 예: 100 slots → $2,000/월 ≈ 온디맨드 400TB 처리량에 해당

보통 온디맨드 기준으로 스캔 바이트 줄이는 것을 목표로 합니다.

 

4. Partitioning(파티셔닝)

https://docs.google.com/presentation/d/1a3ZoBAXFk8-EhUsd7rAZd-5p_HpltkzSeujjRGB2TAI/edit?slide=id.g10eebc44ce4_0_41#slide=id.g10eebc44ce4_0_41

 

BigQuery 파티셔닝은 대표적으로 3가지 방식이 있습니다.

    • Time-unit column 기반 (DATE/TIMESTAMP 컬럼)
    • Ingestion time(_PARTITIONTIME) 기반
    • Integer range partitioning

- 시간 파티션은 일 단위가 기본이며(일/시/월/년 가능), 파티션 수는 4000개 제한이 있습니다.

- 쿼리에서 파티션 컬럼으로 필터링하면 해당 파티션만 읽게 되어 스캔량이 줄어들게 됩니다.

 

 

5. Clustering(클러스터링) + 자동 리클러스터링

https://docs.google.com/presentation/d/1a3ZoBAXFk8-EhUsd7rAZd-5p_HpltkzSeujjRGB2TAI/edit?slide=id.g10eebc44ce4_0_47#slide=id.g10eebc44ce4_0_47

 

클러스터링은 "컬럼 값을 기준으로 데이터를 함께 모아두는(co-locate) 정렬/배치 전략"입니다.

    • 지정한 컬럼이 관련 데이터를 같은 블록 근처에 두도록 유도
    • 컬럼 순서가 중요(정렬 우선순위가 됨)
    • 필터/집계 쿼리 성능 개선에 유리
    • 최대 4개 컬럼까지 지정 가능

- BigQuery는 자동 리클러스터링을 수행합니다.

- 신규 데이터가 들어오면 기존 블록 키 범위와 겹치면서 정렬 성질이 약해질 수 있는데, 이를 백그라운드에서 복구해 성능 특성을 유지합니다.

- 파티션 테이블은 파티션 범위 내에서 클러스터링이 유지됩니다.

 

 

6. Partitioning vs Clustering 선택 가이드

Partitioning이 먼저인 경우

    • 파티션 단위 관리(특정 기간 삭제/만료 등)가 필요
    • 쿼리 필터가 “단일 시간 컬럼 중심”으로 강하게 걸림
    • 비용을 “파티션 프루닝으로” 예측 가능하게 만들고 싶음

Clustering이 더 나은 경우(또는 병행)

  • 파티셔닝만으로는 그라뉼러리티가 부족함
  • 필터/집계가 여러 컬럼에 걸쳐 자주 발생
  • 파티션이 너무 잘게 쪼개져(파티션당 <1GB) 효율이 떨어지거나,
  • 파티션이 너무 많아져 제한(4000)을 압박하거나,
  • 잦은 변경/머지로 많은 파티션이 계속 수정됨

 

7. BigQuery Best Practices (비용/성능)

비용 절감

    • SELECT * 피하기
    • 실행 전에 쿼리 비용(스캔 바이트) 확인
    • 파티션/클러스터 테이블 활용
    • 스트리밍 인서트는 주의
    • 중간 결과를 단계별로 물리화(materialize)

성능(쿼리)

  • 파티션 컬럼으로 필터링
  • (분석 목적이면) 비정규화/중첩 컬럼 활용 고려
  • 조인 전에 데이터량 줄이기
  • WITH를 prepared statement처럼 남발하지 않기
  • 과도한 샤딩(oversharding) 피하기
  • JS UDF 피하기, 근사 집계(HLL++) 활용
  • 조인은 큰 테이블을 먼저 두고(행 수 기준), 작은 테이블을 뒤로 두는 패턴 권장

 

8. BigQuery Internals: 왜 컬럼형이 유리한가

https://docs.google.com/presentation/d/1a3ZoBAXFk8-EhUsd7rAZd-5p_HpltkzSeujjRGB2TAI/edit?slide=id.g10eebc44ce4_0_91#slide=id.g10eebc44ce4_0_91

 

BigQuery는 컬럼 지향(column-oriented) 접근을 통해 필요한 컬럼만 읽는 방식을 사용합니다. 

  • 선택한 컬럼이 많을수록 읽는 컬럼 블록이 늘어남
  • 파티션/클러스터링이 안 되어 있으면 읽어야 하는 블록이 더 커짐

 

9. (실습 코드) External Table → Partition/Cluster 테이블로 최적화하기

9.1 GCS의 Parquet를 External Table로 붙이기

CREATE OR REPLACE EXTERNAL TABLE `my_proj.my_ds.yellow_2024_ext`
OPTIONS (
  format = 'PARQUET',
  uris = ['gs://<bucket>/yellow/yellow_tripdata_2024-*.parquet']
);
  • External Table은 저장은 GCS, 쿼리는 BQ에서 수행합니다.
  • 반복 분석/과제 수행 시엔 물리 테이블로 한번 적재하는 것이 스캔/성능/기능 면에서 일반적으로 유리합니다.

 

9.2 Partition + Cluster 적용한 물리 테이블 생성

항상 tpep_dropoff_datetime로 필터하고, VendorID로 정렬/그룹이 잦다면 전형적으로 아래 전략이 유리합니다.

CREATE OR REPLACE TABLE `my_proj.my_ds.yellow_2024_opt`
PARTITION BY DATE(tpep_dropoff_datetime)
CLUSTER BY VendorID AS
SELECT * FROM `my_proj.my_ds.yellow_2024_ext`;
 
  • PARTITION BY DATE(tpep_dropoff_datetime): 시간 범위 필터 시 파티션 프루닝
  • CLUSTER BY VendorID: VendorID 중심의 필터/집계/정렬 성능 개선

9.3 쿼리 비용(estimated bytes) 줄이는 패턴

 
-- 나쁜 패턴(학습/실습에서 흔히 비용 커짐)
SELECT * FROM `my_proj.my_ds.yellow_2024_opt`;

-- 좋은 패턴(필요 컬럼만 + 파티션 필터)
SELECT VendorID, COUNT(*) AS trips
FROM `my_proj.my_ds.yellow_2024_opt`
WHERE DATE(tpep_dropoff_datetime) BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY VendorID;

 

10. 참고자료/출처