빅쿼리 파티션

파티션 설계와 활용

개요

BigQuery 파티션은 테이블을 논리적으로 분할하여 쿼리 성능을 향상시키고 비용을 절약하는 핵심 기능입니다. 파티션을 통해 스캔해야 하는 데이터 양을 줄여 더 빠르고 저렴한 쿼리를 실행할 수 있습니다.

파티션의 장점

  • 성능 향상: 필요한 파티션만 스캔하여 쿼리 속도 개선
  • 비용 절약: 스캔하는 데이터 양 감소로 비용 절약
  • 관리 효율성: 파티션 단위로 데이터 관리 및 삭제 가능
  • 동시성 개선: 서로 다른 파티션에 대한 동시 작업 가능

파티션 유형

1. DATE 컬럼 파티션

-- DATE 컬럼 기반 일별 파티셔닝 (기본)
CREATE TABLE mydataset.sales_table (
    transaction_id INT64,
    transaction_date DATE,
    amount FLOAT64
)
PARTITION BY transaction_date;

2. TIMESTAMP 컬럼 파티션

-- TIMESTAMP 컬럼 기반 일별 파티셔닝
CREATE TABLE mydataset.events_table (
    event_id INT64,
    event_timestamp TIMESTAMP,
    user_id STRING
)
PARTITION BY DATE(event_timestamp);

-- TIMESTAMP 컬럼 기반 시간별 파티셔닝
CREATE TABLE mydataset.hourly_events (
    event_id INT64,
    event_timestamp TIMESTAMP,
    data STRING
)
PARTITION BY TIMESTAMP_TRUNC(event_timestamp, HOUR);

3. 타임존 기반 파티션

-- KST 기준으로 파티셔닝
CREATE TABLE mydataset.korea_sales (
    transaction_id INT64,
    transaction_timestamp TIMESTAMP,
    amount FLOAT64
)
PARTITION BY DATE(DATETIME(TIMESTAMP(transaction_timestamp), "Asia/Seoul"));

-- 미국 동부 시간대(EST) 기준 파티셔닝
CREATE TABLE mydataset.us_east_sales (
    transaction_id INT64,
    transaction_timestamp TIMESTAMP,
    amount FLOAT64
)
PARTITION BY DATE(DATETIME(TIMESTAMP(transaction_timestamp), "America/New_York"));

4. 수집 시간 파티션

-- UTC 기준 일별 수집 시간 파티셔닝
CREATE TABLE mydataset.ingestion_table (
    id INT64,
    data STRING
)
PARTITION BY _PARTITIONDATE;

타임존 처리

한국 시간대 기준 데이터 조회

-- 한국 시간 기준으로 수집 시간 필터링
SELECT *
FROM mydataset.ingestion_table
WHERE _PARTITIONTIME >= TIMESTAMP("2024-01-01", "Asia/Seoul")
  AND _PARTITIONTIME < TIMESTAMP("2024-01-02", "Asia/Seoul");

-- 한국 시간 기준으로 2024년 1월 1일 데이터 조회
SELECT *
FROM mydataset.events_table
WHERE DATE(event_timestamp, "Asia/Seoul") = "2024-01-01";

특정 파티션에 데이터 삽입

-- 특정 날짜 파티션에 직접 데이터 삽입 (한국 시간 기준)
INSERT INTO mydataset.sales_table$20240101
SELECT 
    transaction_id,
    DATE("2024-01-01") as transaction_date,
    amount
FROM source_table
WHERE DATE(transaction_timestamp, "Asia/Seoul") = "2024-01-01";

DST(Daylight Saving Time) 고려

-- DST 변경 시점을 고려한 쿼리 작성
SELECT 
    event_timestamp,
    DATETIME(event_timestamp, "America/New_York") as local_time,
    -- DST 정보 확인
    EXTRACT(DAYOFYEAR FROM DATETIME(event_timestamp, "America/New_York")) as day_of_year
FROM mydataset.events_table
WHERE DATE(event_timestamp, "America/New_York") = "2024-03-10"; -- DST 시작일

성능 최적화

파티션 프루닝 활용

-- ✅ 좋은 예: 파티션 컬럼을 직접 필터링
SELECT * FROM mydataset.sales_table
WHERE transaction_date >= "2024-01-01" 
  AND transaction_date <= "2024-01-31";

-- ❌ 피해야 할 예: 함수 적용으로 파티션 프루닝 방해
SELECT * FROM mydataset.sales_table
WHERE DATE_ADD(transaction_date, INTERVAL 1 DAY) >= "2024-01-02";

효율적인 데이터 로드

-- 배치 데이터 로드 시 정확한 파티션 지정
LOAD DATA INTO mydataset.sales_table
PARTITION (transaction_date = "2024-01-01")
FROM 'gs://bucket/sales-20240101.csv'
WITH PARTITION_COLUMNS (transaction_date);

파티션 메타데이터 조회

파티션 정보 확인

-- 모든 파티션 목록과 크기 정보 조회
SELECT 
    partition_id,
    total_rows,
    total_logical_bytes,
    last_modified_time
FROM mydataset.INFORMATION_SCHEMA.PARTITIONS
WHERE table_name = 'sales_table'
ORDER BY partition_id;

파티션 분포 분석

-- 파티션별 데이터 분포 확인
SELECT 
    _PARTITIONTIME,
    COUNT(*) as record_count,
    MIN(event_timestamp) as min_timestamp,
    MAX(event_timestamp) as max_timestamp
FROM mydataset.ingestion_table
WHERE _PARTITIONDATE BETWEEN "2024-01-01" AND "2024-01-07"
GROUP BY _PARTITIONTIME
ORDER BY _PARTITIONTIME;

파티션 관리

파티션 만료 설정

-- 파티션 만료 기간 설정 (90일)
ALTER TABLE mydataset.sales_table
SET OPTIONS (
    partition_expiration_days = 90
);

파티션 삭제

-- 특정 파티션 삭제
DELETE FROM mydataset.sales_table
WHERE transaction_date = "2024-01-01";

CLI를 통한 파티션 관리

테이블 생성

# 파티션 테이블 생성
bq mk \
    --table \
    --time_partitioning_field=transaction_date \
    --time_partitioning_type=DAY \
    mydataset.sales_table \
    schema.json

데이터 로드

# 특정 파티션에 데이터 로드
bq load \
    --source_format=CSV \
    --time_partitioning_field=transaction_date \
    mydataset.sales_table$20240101 \
    gs://bucket/data.csv \
    schema.json

메타데이터 조회

# 테이블 정보 조회
bq show --format=prettyjson mydataset.sales_table

# 파티션 목록 조회
bq ls --format=prettyjson mydataset.sales_table

주요 제한사항

  • 테이블당 최대 4,000개 파티션
  • 파티션 컬럼은 테이블 생성 후 변경 불가
  • 중첩된 파티션 컬럼 지원 안함
  • 파티션 컬럼에 NULL 값이 있으면 __NULL__ 파티션에 저장

모범 사례

  1. 적절한 파티션 크기: 파티션당 1GB 이상 권장
  2. 파티션 필터 사용: 쿼리 시 항상 파티션 필터 사용
  3. 타임존 일관성: 데이터 수집과 조회 시 동일한 타임존 사용
  4. 메타데이터 모니터링: 정기적으로 파티션 크기와 분포 확인
  5. 만료 정책 설정: 불필요한 오래된 파티션 자동 삭제

비용 절약 팁

  • 파티션 프루닝을 통해 스캔 데이터 양 최소화
  • 적절한 파티션 만료 정책으로 스토리지 비용 절약
  • 쿼리 실행 전 예상 스캔 량 확인
  • 파티션별 압축률 최적화

결론

BigQuery 파티션은 대용량 데이터 처리에서 필수적인 기능입니다. 적절한 파티션 전략을 통해 쿼리 성능을 크게 향상시키고 비용을 절약할 수 있습니다. 특히 시계열 데이터나 로그 데이터 처리 시 파티션을 활용하면 큰 효과를 볼 수 있습니다.