[Google BigQuery] WITH문, 성능에 문제없을까?
0. 배경
통계쿼리를 작성할 때 가독성을 고려하지 않고 작성하다보면 주요 지표들을 계산하는 복잡한 로직과 Table 간의 JOIN, 많은 서브쿼리들이 복잡하게 얽혀 매우 복잡한, 가독성을 사실상 거의 포기한 Query가 나오게 됩니다.
하지만 보통 데이터 분석에서 다루는 로그 성격의 정보를 저장하는 테이블들은 아무리 적절히 정제과정을 거처더라도 row수가 매우 많습니다 (1억건도 많지는 않은 편...). 그렇기 때문에 이렇게 거대한 Table들을 모두 JOIN해서 사용하는 것은 아무리 ON 조건을 적절히 잘 건다고 하더라도 상상 이상의 비용이 발생합니다. Google BigQuery 같이 수천대의 분산환경 컴퓨팅 성능을 활용할 수 있는 막강한 성능을 가진 플렛폼을 사용하더라도 분명 결과를 받기까지 상당히 많은 시간이 소요되고, 사용하는 리소스가 많아지기 때문에 비용도 그만큼 많이 발생합니다. 따라서 보통 서브쿼리를 작성하여 쿼리에서 다루는 Table의 사이즈를 줄이고 이를 통해 쿼리 성능개선 및 최적화를 하기 때문에 데이터가 워낙 많은 통계쿼리를 작성하는 경우, 서브쿼리는 거의 필연적으로 등장하게 됩니다.
하지만 이 서브쿼리를 사용하는 순간 쿼리내부에 또 다른 쿼리가 들어가기 때문에 가독성이 깨지기 시작합니다. 들여쓰기가 많아지고, 쿼리의 길이가 점점 길어지기 시작하면서 우리가 흔히 말하는 "읽기 싫은" 쿼리가 만들어지게 됩니다 (꼭 복잡한 통계쿼리가 아니더라도 개인적으로 서브쿼리를 이미 도입하는 시점부터 쿼리의 가독성은 흔들리기 시작한다는 것이 개인적인 생각입니다).
그래서 이러한 가독성 문제를 해결하기 위한 방법으로 "WITH 구문"이 있습니다.
우리가 익숙하게 사용하는 MySQL, Oracle 등 많은 DB들이 이 WITH 구문을 지원합니다. 하지만 이 WITH 구문을 늘 괴롭히며 따라다니는 문제가 한 가지 있습니다. 그것은 바로 "WITH 구문은 성능에 영향을 미친다" 라는 내용입니다.
실제로 Oracle의 경우 WITH 구문에 작성된 쿼리에 대한 실행결과는 가상의 테이블로 구성되어 메모리 공간에 할당됩니다. 만약 해당 쿼리가 여러 곳에서 반복적으로 사용되는 경우, 또 다시 해당 쿼리를 실행할 필요없이 메모리 공간을 바로 참조해서 미리 구성된 테이블을 가져오면 되기 때문에 동일한 쿼리의 중복을 없애 가독성을 향상시킨다는 장점과 동시에 성능상의 이점도 함께 얻을 수 있습니다.
하지만 가상의 테이블들이 WITH 구문의 무분별한 사용으로 인하여 메모리 공간에 많이 올라가거나, row수가 많아 테이블을 지속적으로 메모리에 올려두는 것 자체가 큰 비용이 되는 경우 이는 메모리 공간의 낭비로 이어지게되고, 해당 쿼리에 매핑되는 가상테이블을 찾기위한 탐색, 메모리 공간이 부족해질 경우 메모리 swap 등과 같은 비용들이 추가로 발생하게 되면서 전반적인 시스템의 성능저하로 이어지게 됩니다.
그래서 실제로 Oracle 관점에서 WITH 구문을 바라볼 때에는 다음과 같은 결론을 내립니다.
Oracle에서 WITH 구문 사용은 긍정적 효과(가독성, 성능 향상)를 가져오지만, 무분별하게 사용할 경우 오히려 성능문제가 발생하기 때문에 상황에 맞게 적절히 사용하는 것이 중요하다.
이번 글을 통해서 다루고자 한 질문이자 주제는 "Oracle 기준으로 바라보았을 때 도출한 위와 같은 결론이 Google BigQuery에서도 동일하게 적용되는 가?" 즉, "Google BigQuery도 WITH 구문 많이 사용하면 성능문제 생기나요?" 입니다.
1. 정답
사실 WITH 구문의 사용이 모든 시스템에서 성능저하 문제를 발생시키는 것은 아닙니다. 결과부터 말씀드리면 "Google BigQuery에서는 WITH문의 사용이 성능에 영향을 주지 않습니다". 실제 BigQuery 공식 문서에서는 WITH 구문의 사용으로 인한 성능저하에 대한 우려에 대해서 다음과 같이 설명하고 있습니다.
공통 테이블 표현식(CTE)이 있는 WITH 절은 주로 성능이 아닌 쿼리 가독성에 사용됩니다. WITH 절을 추가해도 BigQuery가 임시 중간 테이블을 구체화하지 않습니다.
즉, BigQuery는 Oracle과 달리 WITH 구문으로 작성된 쿼리의 실행 결과를 가상의 임시테이블로 유지하지 않기 때문에 성능에 거의 영향을 주지 않는다는 것입니다. 물론 아무리 가독성을 향상하기 위한 도구적인 개념이더라도 WITH 구문을 무분별하게 사용하는 것은 좋지 않겠지만 성능저하나 리소스 사용한도 초과와 같은 걱정 때문에 WITH 구문을 써야할 곳에 사용하지 못하는 일이 없도록 하자는 것입니다.
2. 결론
다시 정리하면 BigQuery에서는 WITH문의 사용으로 인한 성능저하 문제를 걱정하지 않아도 됩니다. BigQuery가 WITH문을 내부적으로 처리하는 방식이 Oracle과 다른 이유에 대해서 정확히는 알 수 없지만, OLAP 유형 인 BigQuery가 기본적으로 OLTP 유형 인 Oracle에 비해 Table의 row 수가 훨신 많기 때문에(다루는 데이터의 양이 훨신 많기 때문에) WITH문으로 처리된 가상 테이블의 사이즈도 그만큼 클 것이므로 이 모두를 메모리에 올려두는 것이 부담이기 때문일 것이라고 생각됩니다.
만약 BigQuery를 처음 사용하는 입장에서 Oracle에서의 WITH문이 성능에 영향을 준다는 사실만 알고 있는 상황이었다면, 쿼리를 작성하면서도 WITH문의 사용을 지양 또는 최소화 하는 방향으로 쿼리를 작성하려고 했을 것 입니다. 하지만 살펴본 것처럼 BigQuery와 Oracle이 서로 WITH 구문을 바라보는 관점이 서로 달랐기 때문에 BigQuery에서는 WITH 구문의 사용으로 인한 성능저하, 리소스 사용량 등과 같은 내용을 걱정을 할 필요가 없었습니다.
즉, 시스템마다 설계 목적에 따라 지향하는 컨셉이 다르고, 그 차이로 같은 개념이나 기능에 대한 내부구현이 달라지기 때문에 이를 어떤 관점으로 바라보느냐에 따라서 결론이 달라질 수 있는 질문들이라면 공식문서를 참고하여 결론내리는 습관을 들이는 것이 중요할 것 같습니다.
참고자료
https://cloud.google.com/bigquery/docs/best-practices-performance-communication?hl=ko
'Computer Science > 데이터 베이스' 카테고리의 다른 글
JSON_CONTAINS(), IN 절의 검색 대상을 여러 개로 확장하는 전략 (1) | 2024.04.14 |
---|---|
간단하게 살펴보는 빅데이터 분석과 관련 개념들 (1) | 2023.12.10 |
[Google BigQuery] 1라인 쿼리에서 변수를 사용하고 싶을 때 (0) | 2023.04.03 |
댓글
이 글 공유하기
다른 글
-
JSON_CONTAINS(), IN 절의 검색 대상을 여러 개로 확장하는 전략
JSON_CONTAINS(), IN 절의 검색 대상을 여러 개로 확장하는 전략
2024.04.14 -
간단하게 살펴보는 빅데이터 분석과 관련 개념들
간단하게 살펴보는 빅데이터 분석과 관련 개념들
2023.12.10 -
[Google BigQuery] 1라인 쿼리에서 변수를 사용하고 싶을 때
[Google BigQuery] 1라인 쿼리에서 변수를 사용하고 싶을 때
2023.04.03