# 파티션 필터와 최대 청구 바이트

미리보기, 필요한 컬럼 선택, 파티션 필터, named parameter, dry run, maximum bytes billed를 이용해 BigQuery 쿼리의 스캔량과 비용을 실행 전에 통제합니다.

- 카테고리: BigQuery
- 소요 시간: 약 11분
- 난이도: 중간
- 업데이트: 2026.09.02
- 원문: /wiki/playbook/bigquery-checklist/bigquery-query-and-cost-control-guide

## 목차

- [비용 계산 기준](#cost-model)
- [1단계 · 미리보기](#step-1)
- [2단계 · 쿼리 작성](#step-2)
- [3단계 · 예상 스캔량](#step-3)
- [4단계 · 최대 바이트](#step-4)
- [클라이언트 안전장치](#client)
- [리뷰 체크리스트](#review)
- [코드로 안전한 조회](#code-examples)
- [자주 묻는 질문](#faq)

BigQuery 온디맨드 쿼리는 결과 행 수가 아니라 **읽은 데이터 바이트**를 기준으로 비용을 계산합니다. 안전한 쿼리는 실행 전에 예상 바이트를 확인하고, 필요한 컬럼과 파티션만 읽으며, 최대 청구 바이트를 코드와 콘솔 양쪽에 설정합니다.

> **이 문서 핵심**
>
> - **대상.** 콘솔 또는 애플리케이션에서 SQL을 실행하는 사용자.
>
> - **완료 후.** 파티션 필터·파라미터·최대 바이트가 적용된 조회 패턴을 사용합니다.
>
> - **다음.** 데이터 갱신은 [쓰기·MERGE·CDC 가이드](/wiki/playbook/bigquery-checklist/bigquery-data-write-and-cdc-guide)에서 다룹니다.

## 결과가 10행이어도 수 TB를 읽을 수 있습니다

`LIMIT 10`은 반환 행을 제한할 뿐, 비클러스터 테이블이 읽는 바이트를 자동으로 줄이지 않습니다. 특히 `SELECT *`와 날짜 필터 없는 조회가 함께 쓰이면 작은 결과를 얻으면서도 전체 테이블을 스캔할 수 있습니다.

| 습관 | 비용에 미치는 영향 | 권장 방식 |
| --- | --- | --- |
| `SELECT *` | 사용하지 않는 컬럼까지 읽음 | 필요 컬럼을 이름으로 지정 |
| 파티션 필터 없음 | 전체 날짜 파티션 후보 | 파티션 컬럼 범위를 필수화 |
| `LIMIT`만 사용 | 반환량만 제한 | 미리보기 또는 파티션·컬럼 축소 |
| 실행 후 비용 확인 | 실수 쿼리를 막지 못함 | dry run과 maximum bytes billed |

![전체 테이블에서 파티션과 필요한 컬럼만 남겨 스캔 바이트를 줄이는 흐름](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/00-query-scan-reduction.png)

> **한눈에 보기.** 날짜 파티션을 먼저 줄이고 필요한 컬럼만 선택할수록 읽는 바이트가 작아집니다.

Google Cloud의 [BigQuery 비용 최적화 권장사항](https://cloud.google.com/bigquery/docs/best-practices-costs)도 쿼리 전에 비용을 추정하고 읽는 데이터를 줄이는 방식을 권장합니다.

## 1단계. 데이터 모양은 미리보기로 먼저 확인

테이블 상세의 **미리보기** 탭은 쿼리를 실행하지 않고 일부 행을 보여 줍니다. 컬럼 이름, 타입, 샘플 값을 확인하려고 `SELECT *`를 실행할 필요가 없습니다.

![orders 테이블 미리보기의 네 개 주문 행](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/01-table-preview.png)

> **화면 1.** 쿼리 전에 테이블 구조와 샘플 행 확인.

> **팁**
>
> CLI에서는 `bq head`, API에서는 tabledata.list 같은 미리보기 경로를 사용할 수 있습니다. 대규모 테이블을 살펴보는 첫 단계로 일반 쿼리보다 적합합니다.

## 2단계. 필요 컬럼과 파티션 범위를 함께 지정

샘플 주문 테이블은 `order_date`로 파티션되어 있습니다. 고객별 주문을 조회할 때도 먼저 날짜 범위를 고정하고, 필요한 컬럼만 선택합니다.

**파티션을 제한한 조회**
```sql
SELECT
  order_id,
  order_status,
  order_amount,
  updated_at
FROM `hurdlers-bq-dev-guide-260902.developer_guide.orders`
WHERE order_date BETWEEN @start_date AND @end_date
  AND customer_id = @customer_id
ORDER BY updated_at DESC;
```

파라미터는 값에 사용하고, 프로젝트·데이터셋·테이블 같은 식별자는 허용 목록으로 관리합니다. BigQuery의 [파라미터 쿼리](https://cloud.google.com/bigquery/docs/parameterized-queries)는 값 타입을 분리하고 쿼리 로그에서 파라미터 값을 숨깁니다.

## 3단계. 실행 전에 예상 처리량 확인

SQL 편집기 우측 상단의 처리량 표시를 확인합니다. 이 문서의 작은 샘플은 150바이트였지만, 운영에서는 MB·GB·TB 단위를 반드시 구분해야 합니다.

![파티션 필터 쿼리와 150바이트 예상 처리량](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/02-query-cost-estimate.png)

> **화면 2.** 실행 전 예상 처리량과 파티션 조건 확인.

![고객 CUS-001의 주문 두 행을 반환한 쿼리 결과](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/03-query-results.png)

> **화면 3.** 실행 후 결과 행과 쿼리 완료 상태 확인.

**CLI dry run**
```bash
bq query --use_legacy_sql=false --dry_run \
  --project_id=hurdlers-bq-dev-guide-260902 \
  --location=asia-northeast3 \
  'SELECT order_id FROM `hurdlers-bq-dev-guide-260902.developer_guide.orders` WHERE order_date = DATE("2026-09-02")'
```

dry run은 쿼리를 실행하지 않고 유효성과 예상 처리 바이트를 계산하며, 별도의 쿼리 요금이 청구되지 않습니다.

## 4단계. 청구 가능한 최대 바이트 설정

SQL 편집기의 **더보기 → 쿼리 설정**을 열고, 고급 옵션에서 청구 가능한 최대 바이트를 설정합니다. 예상량이 한도를 넘으면 BigQuery가 실행을 거부합니다.

![BigQuery SQL 편집기의 더보기 메뉴에서 쿼리 설정 선택](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/04-query-settings-menu.png)

> **화면 4.** 더보기 메뉴에서 **쿼리 설정** 진입.

![쿼리 설정의 청구 가능한 최대 바이트 입력](/wiki-assets/playbook/bigquery-query-and-cost-control-guide/05-query-max-bytes.png)

> **화면 5.** 예시는 1GiB인 `1073741824`바이트로 제한.

> **주의**
>
> 최대 바이트는 조직의 월 예산 자체를 멈추는 기능이 아니라 **개별 쿼리 안전장치**입니다. 예산 알림, 할당량, 대시보드와 함께 운영해야 합니다.

## 애플리케이션 코드에도 같은 안전장치 적용

**Node.js 쿼리 작업 설정**
```typescript
const [rows] = await bigquery.query({
  query,
  params: { startDate, endDate, customerId },
  location: "asia-northeast3",
  maximumBytesBilled: "1073741824",
  labels: { app: "orders-api", feature: "order-history" },
});
```

- **location**: 데이터셋 region과 동일하게 고정
- **maximumBytesBilled**: 엔드포인트가 허용할 최대 스캔량
- **labels**: 앱·환경·기능별 비용과 작업 추적
- **timeout·retry**: 무한 대기와 무제한 재시도 방지
- **dry run**: 사용자 작성 SQL이나 배치 배포 전 검증

> **정보**
>
> 재시도는 읽기 쿼리와 멱등성이 보장된 작업에만 신중히 적용합니다. 쓰기 작업을 같은 job ID 없이 반복하면 데이터가 중복될 수 있습니다.

## SQL 리뷰 체크리스트

- `SELECT *` 대신 필요한 컬럼만 명시했는가
- 파티션 컬럼 필터가 실제로 pruning 가능한 형태인가
- 사용자 입력은 named parameter로 전달하는가
- 실행 전 dry run 또는 콘솔 예상 바이트를 확인했는가
- maximum bytes billed와 location이 코드에 명시됐는가
- 대시보드 반복 조회라면 집계 테이블·구체화 뷰·캐시를 검토했는가

named parameter, 파티션 필터, location, maximum bytes billed를 함께 적용한 전체 파일을 실행합니다.

## 자주 묻는 질문

### LIMIT을 쓰면 비용이 줄지 않나요?

일반적인 비클러스터 테이블에서는 LIMIT이 반환 행만 줄이고 읽는 바이트는 줄이지 않습니다. 컬럼 선택과 파티션 필터가 먼저입니다.

### 쿼리 결과 캐시는 비용이 없나요?

동일 쿼리가 캐시 조건을 충족하면 캐시 결과를 재사용할 수 있습니다. 하지만 캐시를 비용 제어의 유일한 수단으로 보지 말고 SQL 자체의 스캔 범위를 줄여야 합니다.

### 파티션 필터를 함수로 감싸도 되나요?

표현식 형태에 따라 파티션 pruning이 약해질 수 있습니다. 가능한 한 파티션 컬럼을 직접 비교하고, 실행 전 예상 바이트로 실제 pruning 여부를 확인합니다.

## Navigation

- [전체 플레이북 Markdown sitemap](/wiki/playbook/sitemap.md)

### BigQuery

- [BigQuery](/wiki/playbook/bigquery-checklist)
- [BigQuery 온보딩](/wiki/playbook/bigquery-checklist/bigquery-onboarding-guide)
- [BigQuery 인증 설정](/wiki/playbook/bigquery-checklist/how-to-set-up-bigquery-authentication)
- [BigQuery 데이터셋·테이블 설계](/wiki/playbook/bigquery-checklist/bigquery-dataset-and-table-design-guide)
- [BigQuery 쿼리·비용 제어](/wiki/playbook/bigquery-checklist/bigquery-query-and-cost-control-guide) (현재 문서)
- [BigQuery 쓰기·MERGE·CDC](/wiki/playbook/bigquery-checklist/bigquery-data-write-and-cdc-guide)
- [BigQuery 코드 예제 모음](/wiki/playbook/bigquery-checklist/bigquery-code-examples)
- [BigQuery로 들어오는 GA4 데이터](/wiki/playbook/bigquery-checklist/what-is-ga4-data-in-bigquery)
- [BigQuery Studio 인터페이스 이해하기](/wiki/playbook/bigquery-checklist/what-is-bigquery-studio-interface)
- [BigQuery 예상 비용](/wiki/playbook/bigquery-checklist/how-to-estimate-bigquery-costs)
- [무료 버전(샌드박스) 해제해야 하는 이유](/wiki/playbook/bigquery-checklist/why-upgrade-from-bigquery-sandbox)
- [GA4 BigQuery 데이터를 왜 평탄화해야 하나](/wiki/playbook/bigquery-checklist/why-flatten-ga4-bigquery-data)
- [Log Router란?](/wiki/playbook/bigquery-checklist/what-is-log-router)
- [Pub/Sub이란?](/wiki/playbook/bigquery-checklist/what-is-pubsub)
- [Cloud Functions이란?](/wiki/playbook/bigquery-checklist/what-is-cloud-function-and-run)
- [GA4 export 시점에 예약 쿼리 자동 실행하기](/wiki/playbook/bigquery-checklist/how-to-trigger-scheduled-query-on-ga4-export)
- [테이블 정의서는 왜 필요한가](/wiki/playbook/bigquery-checklist/why-table-definition-doc)
- [Event_Flat 테이블 이해하기](/wiki/playbook/bigquery-checklist/what-is-event-flat-table)
- [Item_Performance 테이블 이해하기](/wiki/playbook/bigquery-checklist/what-is-item-performance-table)
