[Dev Blog] MySQL에서 BigQuery로 옮겨 50배 빠른 서비스를 구축한 방법

Kyle Jung
6 min readJun 13, 2024

Intro

BigQuery는 사용하면 MySQL보다 몇 백배나 빠른 효과를 보실 수 있지만 한번 쿼리할때마다 비용이 발생합니다.

따라서 빅데이터셋에 사용하기에 적합하며, BI 성의 통계성 피쳐를 제공할 때 사용하기에 가장 큰 효과를 볼 수 있습니다. 하지만 쿼리 최적화를 하지 않으면 가하급수적인 비용이 발생할 수 있어서 최적화는 필수입니다.

이번 글에서는 클라이원트가 BigQuery로 어떤 문제를 어떻게 해결했는지, 그리고 어떻게 최적화했는지 상세하게 알려드립니다.

Problem

일반 SQL DB로 빅데이터를 다룰 때 항상 가장 어려운 부분은 빠른 조회 속도인 것 같습니다.

특히 대량의 데이터가 담긴 테이블 전체를 특정 조건에 따라 어그리게이션(Aggregation) 하거나 정렬(Ordering)해야하는 니즈가 있다면 인덱스를 전략적으로 잘 설정해야하고, 쿼리 또한 효율적으로 짜야 퍼포먼스가 잘 나옵니다.

하지만 위 방법도 결국 한계가 오는 때가 옵니다. 아무리 최적화를 해도 더 이상 개선할 여지가 없을 때를 맞이하기 마련입니다. 저희도 이 문제를 피해갈 수 없었는데요, 클라이원트의 BI 서비스 중 2020년부터 수집한 최대 750만개의 과거 사업 내용을 실시간으로 검색하고 수요처, 발주 기관 등으로 총 공고 수 및 사업금액 등의 어그리게이션 하여 통계를 매겨야하는 니즈가 있었습니다.

문제는 특정 키워드와 공고일 범위로 검색할 경우 결과가 나오기까지 60초가 넘어가 Timeout 에러까지 발생하는 현상이 있었습니다. API로 데이터를 반환해야하는 상황에서 10초가 넘어가는 것도 서비스에 크리티컬한데 이런 상황은 거의 서비스가 불가능할정도로 만들었습니다.

아래는 MySQL 기준으로 검색했을 때 Cache Limit 문제로 키워드 검색이 안된 예시입니다.

따라서 검색 쿼리를 뜯어보니 아래와 같은 단계가 있었고, 각 단계별로 최적화가 필요한 것을 발견했습니다.

  1. 입력된 키워드 기준으로 공고명과 다양한 필터로 공고 검색.
  2. 기업별, 수요기관별 총 공고 개수 및 금액 어그리게이션.
  3. 업로드 날짜, 금액 기준으로 정렬.

문제는 첫번째 단계를 해결 하는데서부터 막혔다는 것입니다. 750만개 문서 중 자주 발생하는 키워드를 입력했을 경우 탐색하는 데이터량 자체가 너무 많아서 조회 자체가 오래걸렸습니다.

Solution

1. Bigquery 의 효과

다양한 방법을 고민해보았습니다.

  • 미리 데이터를 추출해놓는 방법은 없을까? → 유저가 어떤 키워드랑 필터 조건을 걸지 모른다.
  • ElasticSearch를 활용해볼까? → 처음부터 배우고 PoC진행하기까지 너무 오래걸린다. 샤딩 방법이랑 쿼리 문법 등을 다 처음부터 배워야했다.
  • 쿼리를 최적화 해볼까? → 빅데이터를 다루다보면 쿼리로 최적화로 개선할 수 있는데 한계가 있더라.

그래서 고민에 빠져있었던 와중 GCP BigQuery가 빅데이터 기반 쿼리를 작성하는데 빠르다고 이야기를 들었지만 사실 반신반의 했었습니다.. 같은 SQL 기반인데 얼마나 빠를 수 있는가? 그래도 테이블만 그대로 옮기고 쿼리도 MySQL 기반이랑 거의 유사해서 주요 테이블 하나만 마이그레이션해서 테스팅 해보았습니다.

깜짝 놀랐습니다. 아무런 인덱스도 걸지 않았는데.. 타임아웃이 걸리던 쿼리가 1초만에 돌아가는 것이었습니다.

심지어 GROUP BY 로 통계를 매기는 쿼리도, ORDER BY 로 전체 데이터를 정렬하는 쿼리도 똑같이 빠르게 실행되었습니다.

1초 걸렸습니다

2. 작동 원리

MySQL같은경우 하나의 엔진에서 처리하지만 BigQuery는 여러개의 Compute Engine에서 병렬로 쿼리를 실행시킨 후 결과를 조합해서 보여주는 원리라 가능하다고 합니다.

하지만 병렬로 처리하는 만큼 쿼리 하나하나에 컴퓨팅 자원이 많이 소모되기 때문에 BigQuery는 속도가 빠른 대신에 쿼리 한번 날릴때마다 비용이 발생하게 됩니다.

비용은 쿼리 실행 시 데이터를 조회한 양에 비례해서 발생하고, 1TB 당 대략 8500원정도의 비용입니다. 따라서 위 쿼리 한번 실행 시 400MB 데이터를 조회하는데 3.4원의 비용이 발생했습니다. 300번의 쿼리를 날리면 1000원정도의 비용이 발생한다고 봤을 때 비용이 비싼편은 맞습니다.

추가로 조회하는 컬럼을 늘리거나 조건을 추가할 경우, 더 많은 데이터를 조회하기 때문에 총 조회하는 데이터량이 늘어나서 쿼리 비용이 비싸집니다.

조건 & 반환되는 컬럼 추가 (대략 34->40원)

3. 그러면 비용 최적화는 어떤식으로 해야하는가?

BigQuery 테이블 생성 시 파티셔닝 옵션을 날짜 or 숫자 필드에 걸 수 있습니다.

테이블 자체를 해당 필드 기준으로 분해해서, 쿼리 시 해당 필드에 조건을 거는 방법으로 조회되는 데이터 범위를 좁힐 수 있게 됩니다.

예를들어 RGST_DT (업로드 날짜) 기준으로 1달씩 테이블을 파티셔닝 했을 때, 5월치 데이터에 대한 조건을 걸면 5월에 해당하는 데이터에만 비용이 발생하게 됩니다. 아래 스크린샷을 보시면 조회된 데이터가 12MB밖에 되지 않아 33배정도 비용을 절감한 것을 보실 수 있습니다.

추가로 서비스에서 1달 기준으로 기본 날짜 범위를 설정해두어 전체 조회하는 빈도수를 줄인다면 비용을 더 절감할 수 있겠죠 🙂

마치며

BigQuery는 말그대로 Big 데이터를 조회할 때 가장 효과적입니다. 생각보다 셋업하는것도 쉽고, 쿼리도 SQL 문법 그대로 사용할 수 있기 때문에 진입장벽이 높지도 않습니다. (역시 갓구글)

다만 성능이 좋은만큼 비용이 많이 발생하는 것도 사실이니 조회하는 데이터를 줄이고, 파티셔닝도 자주 사용되는 필드 기준으로 설정해두어서 서비스에 활용하려면 비용 최적화는 꼭 신경써야 하는 부분입니다.

BigQuery가 MySQL같은 일반 DB를 대체로 사용하기에는 효과적이지 않다고 여겨집니다. 가벼운 쿼리도 실행할 때마다 비용이 발생하고, 가벼울수록 MySQL 이 더 빠르기 때문입니다, 따라서 BigQuery가 꼭 필요한 기능들 위주로 일반 DB와 같이 사용하는게 효과적입니다.

--

--

Kyle Jung

Software Engineer who aims to make the world a better place by helping people discover their potential