💡 이번 포스팅에서는 이런 것들을 다뤄요
BigQuery는 대용량 데이터 분석을 위한 서버리스 데이터 웨어하우스로, 최적화된 쿼리를 작성하면 비용 절감과 처리 속도 향상의 효과를 볼 수 있다. 이번 포스팅에서는 구글 빅쿼리를 최적화 하는 네 개의 팁들을 정리해보았다.
1. 불필요한 데이터 스캔 줄이기
2. 파티션 및 클러스터링 사용하기
3. 조인 최적화
4. 뷰(View)/WITH절 활용
1. 불필요한 데이터 스캔 줄이기
BigQuery는 쿼리할 때 테이블의 스캔한 데이터 양(바이트 단위)에 따라 비용이 청구된다.
따라서 필요한 컬럼과 필요한 행만 조회하여 비용과 쿼리 시간을 줄일 수 있다.
-- 비효율적인 쿼리 (모든 컬럼과 모든 행을 스캔)
SELECT *
FROM `my_project.my_dataset.my_table`;
-- 최적화된 쿼리 (필요한 컬럼만 조회하고 WHERE 조건 추가)
SELECT user_id, event_type, event_time
FROM `my_project.my_dataset.my_table`
WHERE event_date = '2024-01-01';
2. 파티션 및 클러스터링 사용하기
BigQuery 테이블을 파티션(partition)과 클러스터(cluster)로 분할하면 쿼리 성능이 향상된다.
- 파티셔닝: 테이블을 특정 컬럼(예: 날짜, 타임스탬프)으로 나누어 쿼리의 스캔 범위를 줄인다.
- 클러스터링: 특정 컬럼의 값을 기준으로 데이터를 정렬해, 쿼리 성능을 향상시킨다.
파티셔닝과 클러스터링의 개념을 간단히 검토하고 쿼리 성능이 향상되는 원리를 살펴보자.
1) 파티셔닝(Partitioning)
파티셔닝(Partitioning)은 테이블을 특정 기준으로 나누어 물리적으로 분할하는 방법이다.
파티셔닝으로 쿼리가 최적화 되는 과정은 다음과 같다.
- 테이블을 파티션 단위로 나누어 저장한다.
-- event_date 컬럼을 기준으로 시간 기반 파티셔닝된 테이블 생성
CREATE TABLE `my_project.my_dataset.my_table`
PARTITION BY DATE(event_time) -- 파티션 기준을 날짜로 설정
AS
SELECT *
FROM `my_project.my_dataset.raw_table`;
- 쿼리가 실행되면, BigQuery가 필요한 파티션만 스캔하여 처리한다.
- 쿼리할 때 WHERE 조건이 파티션 키에 적용되면, BigQuery는 해당 파티션만 읽어들인다.
-- 특정 날짜의 데이터만 조회 (필요한 파티션만 스캔)
SELECT *
FROM `my_project.my_dataset.my_table`
WHERE DATE(event_time) = '2024-01-01';
2) 클러스터링(Clustering)의 원리
클러스터링(Clustering)은 테이블에 있는 데이터를 특정 컬럼 기준으로 정렬하는 방식이다.
클러스터링으로 쿼리가 최적화 되는 과정은 다음과 같다.
- 테이블 내 데이터를 정렬된 블록으로 저장한다.
-- 클러스터 테이블 생성 (user_id, event_type을 기준으로 정렬)
CREATE TABLE `my_project.my_dataset.my_table`
CLUSTER BY user_id, event_type -- 클러스터 기준 컬럼
AS
SELECT *
FROM `my_project.my_dataset.raw_table`;
- 쿼리가 실행되면, BigQuery는 필요한 블록만 스캔하여 데이터를 검색한다.
- 특정 컬럼에 대한 WHERE 조건이 자주 사용될 때 효과적이다.
-- 특정 user_id의 데이터를 조회
SELECT *
FROM `my_project.my_dataset.my_table`
WHERE user_id = 'user_123';
👀파티셔닝/클러스터링 비교 정리
구분 | 파티셔닝(Partitioning) | 클러스터링(Clustering) |
목적 | 테이블을 분할해 데이터 스캔 감소 | 데이터를 정렬해 스캔 범위 축소 |
기준 컬럼 | 보통 날짜, 정수, 범위 컬럼 사용 | WHERE 조건에 자주 사용되는 컬럼 |
물리적 데이터 분리 | 파티션 단위로 물리적 분할 | 테이블 블록 내 데이터 정렬 |
성능 향상 원리 | 필요한 파티션만 읽음 | 필요한 블록만 스캔 |
쿼리 최적화 방식 | WHERE 절에 파티션 키 조건 추가 | WHERE, GROUP BY, ORDER BY 최적화 |
주요 사용 상황 | 특정 기간/범위 데이터 조회 | 특정 키에 대해 빈번한 필터링 발생 |
설정 가능 컬럼 수 | 1개 컬럼만 설정 가능 | 최대 4개 컬럼 클러스터 가능 |
대표 예시 | DATE(event_time)으로 파티셔닝 | user_id, event_type으로 클러스터링 |
데이터 관리 | 신규 데이터 삽입 시 파티션 자동 추가 | 자동 정렬 및 블록 생성 |
3. 조인(Join) 최적화하기
- WITH 절을 사용해 조인 전에 필터링하여 스캔 범위를 줄인다
- Broad Join을 피하고 키 값에 인덱스 역할을 수행할 수 있는 컬럼으로 조인하기
-- 비효율적인 쿼리 (필터가 조인 후에 적용됨)
SELECT a.user_id, b.order_id
FROM `my_project.dataset.user_data` a
JOIN `my_project.dataset.order_data` b
ON a.user_id = b.user_id
WHERE a.region = 'US';
-- 최적화된 쿼리 (필터를 조인 전에 적용)
WITH filtered_users AS (
SELECT user_id
FROM `my_project.dataset.user_data`
WHERE region = 'US'
)
SELECT a.user_id, b.order_id
FROM filtered_users a
JOIN `my_project.dataset.order_data` b
ON a.user_id = b.user_id;
4. 중첩 쿼리 피하고 뷰(View) / WITH절 활용하기
- 자주 사용하는 복잡한 쿼리를 뷰(View)로 생성하고 필요한 곳에서 사용하기
-- 뷰 생성
CREATE VIEW `my_project.dataset.user_summary` AS
SELECT user_id, COUNT(order_id) AS order_count
FROM `my_project.dataset.order_data`
GROUP BY user_id;
-- 뷰를 사용하는 최적화된 쿼리
SELECT *
FROM `my_project.dataset.user_summary`
WHERE order_count > 10;
- 중첩 쿼리를 피하고 WITH 절을 사용하는 쿼리 스타일로 변경하기
👀최적화 방법 정리
최적화 방법 | 설명 |
불필요한 데이터 스캔 줄이기 | WHERE 절로 스캔 범위 축소하여 SELECT * 대신 필요한 컬럼만 조회 |
파티션 및 클러스터링 | PARTITION BY, CLUSTER BY |
조인 최적화 | 조인 전에 필터링 수행 |
뷰(View)/WITH절 활용 | 복잡한 쿼리를 View, WITH로 재사용 |
'👩🏻💻TECH > 개념정리' 카테고리의 다른 글
[개념정리] Apache Spark 개요 (1) | 2024.12.20 |
---|---|
[개념정리] On-premise, Cloud, Serverless 데이터 웨어하우스 (0) | 2024.12.09 |
[개념정리] Airflow: DAG, Task, Operator (0) | 2024.12.02 |
[개념정리] 데이터 모델링: 모델링의 단계, 구성요소 (0) | 2024.11.24 |
[개념정리] 데이터베이스 정규화 (3) | 2024.11.22 |