Search

[번역] 빅쿼리는 생각보다 쌉니다

Subtitle
몇가지 규칙만 알고 있다면 빅쿼리는 최고의 가성비입니다
Index
Bigquery
Date
2024/05/24
2 more properties
해당 포스트는 원 글인 BigQuery is much cheaper than you think에서 중요한 부분만 요약하여 번역한 글 입니다. 온전한 이해를 원하신다면 원문을 읽으시는 것을 추천드립니다.
빅쿼리는 최신 클라우드 분석 데이터베이스이지만 가격이 비싸다는 평판이 많았습니다. 하지만 이것은 더 이상 아니라고 이야기할 수 있습니다. 빅쿼리 가격 계산 정책이 바뀌면서 구글은 2023년에 굉장히 흥미로운 업데이트를 가지고 왔습니다.
여기서는 그에 대한 3가지 주제를 다룰 예정입니다.
스토리지 가격 모델 선택이 청구서에 미치는 영향
멀티 프로젝트 사용을 통해 반복되는 파이프라인 처리량을 늘리기
세분화된 쿼리 실행 가격 전략

1. 피지컬 스토리지 가격 모델을 사용하세요

2022년 8월, 빅쿼리 테이블 저장이 저렴해졌습니다. 정확히는 적절한 가격이 되었다고 표현하는 것이 맞을 것 같네요. 이전에는 공식문서에 이런 식으로 선언하고 있었습니다.
2022년 8월 이전: 스토리지 가격은 압축되지 않은 상태에서 테이블에 저장된 데이터양을 기준으로 책정됩니다.
그리고 새로운 업데이트는 피지컬 스토리지 가격 모델을 소개했는데요. 이 말은 이제 압축된 데이터에 대해 가격을 청구하겠다는 의미입니다.
아래는 각자 다른 압축 정도를 가진 테이블입니다.
Different commpression ratios (9x vs 3x)
90일의 지속시간을 가지고 있는 첫번째 데이터셋을 보면 로지컬에서 피지컬 가격으로 전환하였고 이는 보시다시피 가격이 아래 그림처럼 112,212$에서 27,324$로 내려가는 것을 보실 수 있습니다.
몇 가지 언급할만한 포인트가 있는데
1.
로지컬 스토리지는 디폴트 옵션입니다. 그래서 만약 피지컬 스토리지를 사용하고 싶다면 Advanced 섹션에서 직접 설정해주어야 합니다.
2.
정액제 약정을 사용하는 고객에게는 피지컬 스토리지 요금이 적용되지 않습니다(2023에 폐지되었다고 하네요)
3.
이전 스토리지 요금제와는 달리, 피지컬 스토리지에서는 장애 조치 및 시간 여행 기간에 대한 요금이 포함됩니다. 시간 이동 기간은 직접 구성할 수 있고 최소값은 2일, 장애 복구는 항상 7일입니다. 즉, 고객은 삭제 후 9일 동안 요금을 지불합니다.
그리고 보시다시피 로지컬 요금제를 사용하는 것이 특히 짧은 기간만 보관하는 테이블에게 중요합니다.
핵심 포인트 #1: 빅쿼리 데이터셋을 만들 때 되도록 고급 기능 설정에서 피지컬 스토리지 요금제를 선택하세요.
핵심 포인트 #2: 2022년 8월 이전에 빅쿼리를 구축하고 저장 비용이 너무 비싸다고 결론을 내렸다면, 다시 구성하세요.

2. 멀티 프로젝트를 사용하세요

단일 프로젝트에 얽매이지 마세요. 프로젝트는 단지 병렬 처리의 단위일 뿐입니다! 유리하게 활용하세요. 공식문서에서는 프로젝트를 일종의 리소스 컨테이너로 설명하고 있습니다.
우리는 슬롯 수 한계로 인해 처리량 문제에 직면하곤 합니다(공식문서에 따르면 2000개 정도가 적당하다고 함) 테이블 사이즈와 처리 로직에 따라 쿼리는 실행하는데 몇시간까지 걸릴 수 있습니다. 이를 해결할 수 있는 방법을 소개합니다.

Step #1. 서브 파티셔닝

동일한 청크로 워크로드를 분할하기 위해, 우리는 인풋을 쪼개야 합니다. 이렇게 하면 데이터를 병렬로 처리할 수 있습니다. 저는 이 프로세스를 서브 파티셔닝이라고 부르는데 이유는 빅쿼리의 파티셔닝과 의미가 충돌할 수 있기 때문입니다.
빅쿼리는 이것을 지원하지 않기 때문에 우리는 이를 직접 수동으로 구현해야 합니다.
CREATE TABLE IF NOT EXISTS warehouse.input.impressions_partitioned ( dt DATE, -- partitioning key ts TIMESTAMP, request_id STRING, -- alternative "primary key" identifier user_id STRING, -- "primary key" identifier device_type STRING, country STRING, ipv4address STRING, impression STRUCT< provider_id STRING, segments ARRAY<INT> >, part INT -- subpartitioning key ) partition by dt cluster by part, device_type, user_id;
SQL
복사
위의 쿼리를 보면 우리는 user_id라는 식별자를 가지고, 서브 파티셔닝은 user_id의 해시값이나 이를 hash(user_id) % num_parts을 의미하는 part라는 컬럼으로 접근합니다.
bq load \ --source-format=ORC \ --hive_partitioning_mode=AUTO \ --hive_partitioning_source_uri_prefix='gs://bucket/folder/' \ --time_paritioning_field='dt' \ --clustering_fields='part,device_type,user_id' \ --project_id=batch-job-1 \ warehouse.input.impressions \ 'gs://bucket/folder/dt=2023-10-01/part=0000/*'
Bash
복사
위의 작업은 우리가 나눈 서브 파티셔닝으로 병렬처리하는 모습을 보여주고 있습니다.

Step #2: 서브 파티션을 병렬로 처리하라

집계하는 디멘젼이 많아질수록 지수적으로 느려지게 될 것입니다. 우리의 첫번째 클러스터링 키는 part이기 때문에 쿼리는 테이블에서 그 부분만 스캔할 것입니다.
bq query --project=batch-job-1 '... and part between 0 and 64 ...' bq query --project=batch-job-2 '... and part between 64 and 128 ...'
Bash
복사
핵심 포인트 #1: 워크로드를 분할할 수 있는 컬럼을 만들어 여러 프로젝트의 병렬 처리를 위한 대규모 데이터셋을 준비하세요
제 생각에 프로젝트를 분리하는 것은 조금 귀찮고 쉽지 않은 작업이라고 생각하는데요. 저자 또한 개인적인 기호라고 이야기 하고 있습니다. 확실히 프로젝트별로 데이터셋을 분리하면 병렬 처리에는 유리할 지 모르겠지만 개인적으로는 관리 측면에서 꽤나 큰 손해라는 생각은 드네요. 각자의 상황에 맞게 취사선택을 하면 좋은 부분인 것 같습니다

3. 온디멘드와 슬롯 시간 쿼리 가격의 균형을 맞추세요

빅쿼리 가격 정책은 크게 두 가지로 설명할 수 있습니다.
1.
On-demand (per TiB): 각 쿼리의 용량으로 청구됩니다.
2.
Capacity (per slot-hour): 슬롯 단위로 컴퓨팅 용량에 따라 청구됩니다.
입력 테이블을 확장하는 대규모 셔플 단계(GROUP BY, UNNEST)와 같이 CPU를 많이 사용하는 쿼리에는 많은 CPU가 소모되지만 스캔한 데이터에 대한 비용으로 지불하는 온디맨드 모델을 사용합니다.
많은 데이터를 스캔하지만 적은 데이터를 출력하는 IO-heavy한 쿼리에는 슬롯 시간 모델을 사용합니다(컬럼 한개 업데이트, 평균 계산, 기타 통계 계산)
온디맨드와 슬롯 시간 모델의 가장 큰 차이는 프로젝트의 쿼리 처리량이 온디맨드에서는 보장되지 않는다는 것입니다. 즉, 온디맨드에서는 쿼리를 처리하기 위해 공유 풀에서 슬롯을 빌려야 되기 때문에 사용가능할 때까지 기다려야 할 수 있습니다.
핵심 포인트 #1: 반복되는 쿼리 비용을 가격 정책에 따라 측정하고 가장 최선을 선택하세요.