MySQL 조인 작동 방식에 대한 (매우) 짧은 살펴보기
Source: Dev.to
MySQL 조인 작동 방식
MySQL은 중첩 루프 조인(Nested‑Loop Join, NLJ) 알고리즘을 사용해 조인을 평가합니다. 간단히 말해 첫 번째 테이블의 한 행을 가져와 다음 테이블을 스캔해 일치하는 행을 찾고, 이 과정을 추가 테이블에 대해 반복합니다. 최악의 경우 O(n²) 시간 복잡도가 되지만, 내장 최적화 덕분에 실제 성능은 훨씬 낮게 유지됩니다.
예시 조인
SELECT *
FROM t1
JOIN t2 ON t1.t2_id = t2.id
JOIN t3 ON t2.t3_id = t3.id;
NLJ 알고리즘 의사코드
for each row in t1
for each t2 matching t1.t2_id
for each t3 matching t2.t3_id
return row if join condition is met
각 내부 루프는 외부 루프의 각 행마다 실행되므로, 특히 WHERE 절이나 인덱스가 없을 때 큰 테이블에서는 비용이 급격히 증가할 수 있습니다.
조건 푸시다운
MySQL은 조건 푸시다운을 적용합니다. 즉, WHERE 절의 관련 부분을 모든 조인이 완료된 후가 아니라 각 루프 단계에서 평가합니다.
SELECT *
FROM t1
JOIN t2 ON t1.t2_id = t2.id
JOIN t3 ON t2.t3_id = t3.id
WHERE t2.status = 'active';
위 쿼리에서는 MySQL이 t2를 순회하면서 t2.status = 'active' 조건을 필터링하고, 조건을 만족하는 행만 t3 검사에 전달합니다. 이렇게 하면 불필요한 행을 조인하는 일을 피할 수 있습니다.
최적화 팁
- 조인 조건과
WHERE절에 사용되는 컬럼에 선택적인 인덱스를 추가하세요. 인덱스는 MySQL이 관련 없는 행을 건너뛰게 해 주어 스캔해야 할 양을 크게 줄여줍니다. - 성장에 대비하세요: 테이블이 커지면 잘 인덱싱된 조인이라도 비용이 많이 들 수 있습니다. 다음을 고려해 보세요:
- 적절한 경우 정규화를 풀어 복잡한 조인의 필요성을 줄이기.
- 큰 테이블을 파티셔닝하기.
- 쿼리 패턴을 검토하고 효율성을 위해 리팩터링하기.
스키마 설계와 인덱싱에 약간의 사전 준비를 하면 나중에 성능 문제를 크게 줄일 수 있습니다.