빅쿼리는 대용량 데이터 처리를 위해 데이터를 일별로 분리해서 분할 저장하는 파티셔닝 기능을 제공한다. 파티셔닝은 테이블에 파티션 데코레이터를 지정해서 UTC 타임존 기준 원하는 날짜 혹은 데이터 생성 날짜로 데이터를 분할 저장하는 기법이다. 데이터가 날짜 범위로 분할되어 저장하기 때문에 쿼리 요청시 분할 날짜를 이용하여 처리 대상 데이터의 범위를 줄일 수 있는 장점을 가진다.
하지만 파티셔닝은 일기준으로만 데이터가 분할되기 때문에 클러스터링 기능을 통해 특정 필드 기준으로 데이터를 분할 저장하게 할 수도 있다. 클러스터링은 데이터의 특정 필드값(최대4개)을 기준으로 데이터를 정렬한 후 최적화된 크기로 각 파티션안에서 또다시 저장소를 분리하여 저장한다. 날짜를 기준으로 분할되지 않고 특정 필드값을 기준으로 정렬되기 때문에 좀더 유연하게 쿼리의 처리 대상이 되는 데이터의 범위를 줄일 수 있게 된다.
하지만 파티셔닝과 클러스터링이 적용되지 않더라도 크게 걱정하지는 말자. 빅쿼리는 같은 쿼리문의 결과에 대해서는 24시간 가량 캐시가 되고 캐시가 된 쿼리 결과를 다시 요청할때는 비용이 추가로 발생하지 않는다. 또한 테라바이트 수준의 데이터에 대해서도 쿼리 속도가 1~2초 가량 밖에 걸리지 않기 때문에 성능 문제도 없다.
파티셔닝
파티셔닝은 하나의 테이블을 파티션이라는 단위로 분할하여 저장한다. 데이터 변환기는 테이블을 일별로 나눠서 저장하게 되어 쿼리에서 읽는 범위를 줄여서 쿼리의 성능을 높일 수 있다. BigQuery는 테이블을 수집 시간 기준일이나 지정한 시간 기준일로 나눌 수 있다. 데이터를 처리시 BigQuery 테이블 대상을 지정할때 다음과 같이 테이블명 뒤에 수집 시간 날짜를 포함한 것을 볼 수 있다.
fast-archive-274910:dw_datadriver.googlefitness_tbl_bd_datasets$20020519
위와 같이 파티션 데코레이터 지정을 하면 특정 날짜를 기준으로 데이터를 분할해서 저장할 수 있다. 만약 파티션 데코레이션 지정을 하지 않고 다음과 같이 저장할 테이블 대상을 지정한다면 데이터가 생성되는 시점의 시간을 기준으로 데이터가 분할되므로 여러날의 데이터를 처리해도 무조건 처리 시점의 날짜 기준 파티션에 데이터가 모두 추가된다.
fast-archive-274910:dw_datadriver.googlefitness_tbl_bd_datasets
파티션을 나눈 테이블을 적용한 데이터 변환기에 의해 생성된 테이블의 정보는 다음과 같다.

이때 분할 기준은 일(Day)로 지정되어 있고 분할 입력란이 수집 날짜 기준으로 파티셔닝 되어 있다는 표시인 _PARTITIONTIME 으로 지정되 있는 것을 볼 수 있다. 테이블명에 수집날짜을 20200522로 지정했으므로 _PARTITIONTIME 역시 2020년 5월 22일로 저장되어 있을 것이다. 빅쿼리에서 다음 쿼리를 실행해보자
SELECT DATE(_PARTITIONTIME) as date, * FROM `fast-archive-274910.dw_datadriver.googlefitness_tbl_bd_datasets`;
면 각 열의 수집 시간이 모두 2002년 5월 19일로 되어 있는 것을 확인할 수 있다.

이후 이렇게 수집된 날짜의 정보인 _PARTITIONTIME 을 기준으로 쿼리를 요청하면 쿼리에서 읽는 범위를 제한할 수 있기 때문에 계속 데이터가 추가되더라도 데이터베이스의 전체적인 성능이 저하되지 않게 된다. 파티셔닝 기능을 쓰지 않거나 검색 쿼리에 _PARTITIONTIME을 지정하지 않으면 전체 테이블에 대해 조회가 일어나므로 서비스 사용 비용이 늘어날 것이므로 주의가 필요하다.
예를 들어 다음과 같이 전체 테이블을 대상으로 쿼리를 요청한 후 화면 하단의 실행정보 탭을 살펴보자. 다음과 같이 쿼리가 1.3MB의 데이터를 대상으로 입력과 출력 모두 5,546개의 행의 정보를 처리한 것을 볼 수 있다.

하지만 다음과 같이 _PARTITIONTIME으로 조건을 걸면 869.2KB를 대상으로 3652개 행의 정보만을 처리하는 것을 확인할 수 있다.

따라서 데이터 분석을 위해 테이블 정보에 접근할때 최대한 파티셔닝 처리를 되게끔 주의하면서 사용해야 한다. 이 책의 예제에서는 UTC기준의 데이터를 한국 기준 타임존으로 모두 변환해서 출력하기 때문에 파티셔닝이 적용되는 쿼리를 사용하고 있지는 않다. 하지만 특정 기간 동안의 결과가 보여주는 리포트를 추가로 만든다면 파티셔닝을 적용하여 성능을 올릴 수 있을 것이다.
클러스터링
파티션을 나눈 테이블을 만들고 클러스터링을 설정한 테이블의 정보는 다음과 같다. 맨 아래를 살펴보면 클러스터링 기준에 user_id 필드값이 포함된 것을 볼 수 있다. 만약 여러면의 데이터가 들어온다면 앞서 설명한 파티셔닝을 이용해서는 원하는 유저별로 데이터 처리 대상을 줄일 수 없다. 이때 클러스터링 필드를 사용해서 유저 아이디별로 데이터 처리 대상을 분할할 수 있다.

다음 쿼리문을 통해 파티셔닝이 적용되는 쿼리를 살펴보자.
SELECT * FROM `fast-archive-274910.dw_datadriver.rescuetime_tbl_bd_data` WHERE DATE(_PARTITIONTIME) = "2020-04-16"
다음과 같이 전체 행 866개중 396행을 대상으로 30.4KB 만의 데이터를 대상으로 쿼리 처리가 발생한 것을 볼 수 있다.

그럼 이제 클러스터링 필드로 설정된 user_id를 조건으로 쿼리를 실행해보자. 현재 이 테이블에는 미리 여러명의 user_id를 가진 데이터를 입력해 둔 상태이다
SELECT * FROM `fast-archive-274910.dw_datadriver.rescuetime_tbl_bd_data` WHERE user_id = "leeteam"
역시 866행중 433행을을 대상으로 47.9KB 데이터에 대한 쿼리 처리가 발생한 것을 볼 수 있다.

이렇게 파티션 날짜 기준뿐만 아니라 클러스터링을 이용하면 특정 필드값을 대상으로도 비용을 아낄 수 있는 쿼리를 요청할 수 있게 된다.
쿼리 효율성 테스트하기
구글 클라우드 플랫폼 웹사이트에서 쿼리를 요청하면 쿼리가 처리하는 데이터의 크기를 알 수 있다. 이를 그건로 쿼리의 효율성과 비용을 예상해볼 수 있다. 다만 빅쿼리는 캐시 기능이 있어서 같은 문장의 쿼리를 중복 요청하면 쿼리를 실행하지 않고 기존의 캐시되어 있는 결과를 보여주기 때문에 효율성 체크를 위해서는 캐싱 옵션을 해제하고 테스트해야 한다.
01. 쿼리 편집기에서 쿼리 설정 메뉴를 클릭한다.

02. 리소스 관리 영역에서 “캐시 처리된 결과 사용” 을 체크해제 한후 “저장” 버튼을 클릭한다.

이제 캐싱된 쿼리 결과를 사용하지 않는다. 해당 옵션은 웹페이지의 쿼리 편집기에서 캐시를 해주기 때문에 다른 곳에는 영향을 주지 않는다.
03. 테스트할 쿼리를 입려한다. 쿼리 입력시 오른쪽에 “실행 시 이쿼리가 XKB를 처리합니다” 라는 문구가 등장한다. 이 문자은 쿼리 실행전에 데이터 처리의 양을 예측해주는 기능이다. 실제 과금되는 데이터 처리량은 쿼리 후 결과를 보고 분석하는 것이 정확하다.

04. 쿼리를 요청하면 쿼리 완료 문자열 오른쪽에 처리시간과 처리된 데이터 용량이 출력된다. 그리고 실행 세부정보 탭에는 몇행의 데이터가 처리 대상에 포함되었는지 확인할 수 있다. 이 용량과 행의 수를 테이블의 전체 데이터양과 행의 수와 비교해서 얼마나 효율적으로 처리되었는지 확인할 수 있다.

글 잘 읽었습니다. 다만 본문의 사진이 짤린것 같네요
앗 감사합니다. 이미지 링크가 깨져 있엇네요 ㅠㅠ
우와 궁금했던 부분이 정확하게 해소된 글입니다.. 감사합니다 🙂
도움이 되었다니 다행이네요!! 잘못된점 있으시면 피드백 부탁드리겠습니다 ^^