12억개가 넘는 row를 만지게 되었다... 근데 fk, indexing도 없고 원테이블로 구성되어 있는데 마이그레이션은 하지 않고 현재 구조에서 최대의 퍼포먼스를 내야 한다고 말씀하셨다.
count만 찍어도 4분정도 걸리는 테이블인데 도대체 쿼리를 어떻게 해야할지 막막했지만 15년동안 개발하신 파트장님이 옆에서 쿼리 짜는걸 보고 얻은 인사이트에 대해 적어보려고 한다.
기존 쿼리
select
i.key as key
, i.service_key as serviceKey
, i.address as address
, i.addressA as addressA
, i.addressN as addressN
, i.created_at as createdAt
, d.title
from info i
left outer join config c on c.info_key = i.service_key
left outer join delivery d on d.key = c.delivery_key
where i.key = 27
order by i.created_at desc;
간단한 select문이지만 fk가 없고 indexing이 되어 있지 않아서 이 쿼리가 4분넘게 걸리길래 그냥 쿼리툴을 꺼버리고 다시 실행했다.
info에서 5억건
config에서 1000만건
delviery에서 100만건
애초에 5억 * 1000만건 * 100만건 이걸 풀스캔을 떠서 조인을 해서 찾아오니까 오래걸릴 수 밖에 없다. 설계를 잘하자...
최적화한 쿼리
select
i.key as key
, i.service_key as serviceKey
, i.address as address
, i.addressA as addressA
, i.addressN as addressN
, i.created_at as createdAt
, d.title
from (
select
i.key as key
, i.service_key as serviceKey
, i.address as address
, i.addressA as addressA
, i.addressN as addressN
, i.created_at as createdAt
from info i
where i.key = 27
order by i.created_at
) i
left outer join config c on c.info_key = i.service_key
left outer join delivery d on d.key = c.delivery_key
조건이 10개만 가지고 오면 됐었기 때문에 subquery로 10개만 찍어서 가지고 왔더니 돌다가 꺼버렸던 쿼리가 1초내로 떨어지게 됐다. 그렇게 어려운 기술도 아니고 subquery를 모르는 것도 아니었는데 fk나 index를 염두에 두고 개발했기 때문에 쿼리를 이렇게 짜야겠다는 생각자체를 못한 것 같다. mongodb에서 aggregation쓴다고 생각하고 쿼리를 짜야겠다.