Deferred Join이란? - 이론편
Deferred Join을 활용하면 쿼리 속도를 2배 이상 높일 수 있다고 합니다.
Deffered Join이란?
deferred는 지연된 연기된 이라는 사전적 의미를 가집니다.
pagination을 수행할 때 전체 테이블이 아닌 데이터의 하위 집합에서 pagination을 수행합니다.
이 집합은 subquery에 의해 생성되며 나중에 원래 테이블과 join 됩니다.
pagination이 될 때 까지 join 작업이 연기되기 때문에 deffered join이라 불립니다.
전통적인 Pagination
SELECT
*
FROM
people
ORDER BY
birthday, id
LIMIT 20
OFFSET 450000;
people이라는 테이블이 존재하고 생일, ID별로 정렬된 결과를 표기하고 싶습니다.
이때 450,000부터 20개의 레코드를 가져오는 쿼리입니다.
이 쿼리를 수행하는데는 600~700 ms가 수행되고 오프셋이 증가함에 따라 쿼리 실행 속도가 점점 느려집니다.
Deferred join 활용해 보기
SELECT * FROM people
INNER JOIN (
SELECT id FROM people ORDER BY birthday, id LIMIT 20 OFFSET 450000
) AS people2 USING (id)
ORDER BY
birthday, id
using은 두 테이블 간 필드이름이 같은 경우에 join 대신에 활용할 수 있습니다.
이 쿼리를 실행하면 200ms 밖에 걸리지 않습니다.
간단한 쿼리 수정으로 3배 빠른 속도를 보여줍니다.
왜 빠를까?
id 열만 포함하는 데이터의 하위 집합을 생성함으로써 훨씬 작은 데이터 셋으로 페이징을 처리할 수 있게 됩니다.
성능최적화
ALTER TABLE people ADD INDEX birthday (birthday);
birthday에 인덱스를 추가하여 내부 하위 쿼리가 커버링 인덱스를 사용할 수 있도록 만들 수 있습니다.
이제 60ms 밖에 걸리지 않습니다.
기존 페이징보다 10배나 개선된 속도입니다.
커버링 인덱스란 쿼리를 충족시키는데 필요한 모든 데이터를 갖고 있는 인덱스를 말합니다.
참고자료
https://hackmysql.com/post/deferred-join-deep-dive/