IN절 vs JOIN절

joona95·2025년 2월 2일

문제 상황

MD가 담당한 업체들의 정보를 가져오기 위해 SQL문 수정이 필요했다. 이 때 처음에는 간단하게 업체 아이디 값을 인덱스로 가지고 있으니 MD가 담당한 업체 아이디 목록을 가져와서 IN절로 조건을 걸어주면 되겠다고 생각했다.

그러나 하나의 MD 당 몇 개의 업체를 담당할 수 있냐는 제한이 따로 없다는 걸 깨닫고, IN절에 갯수 제한이 있지 않았나 싶었다.

그리고 IN절의 개수가 많아질 경우 사실상 OR절로 작동하는 것으로 알고 있는데 오히려 성능에 문제가 생길 수 있을 것 같았다.

이로 인해 IN절 대신 JOIN절을 사용하기로 결심했고, 이러한 내용에 대해 조금 더 자세히 알아보고 어떤 경우에 어떤 구문을 사용하는 것이 좋을지 알아보기로 했다.


IN절

IN절에서의 데이터 개수 제한

  • PostgreSQL: 명시적으로 제한 없으나 많아지면 성능 저하
    • 대안: 1) JOIN 사용 2) = ANY(ARRAY[...]) 사용
  • MySQL: 명시적으로 제한 없으나 많아지면 성능 저하
    • 대안: 1) JOIN 사용 2) 임시 테이블
  • Oracle: 1000개 제한
    • 대안: 1) JOIN 사용 2) IN + OR 조합 사용
  • SQL Server: 명시적으로 제한 없으나 많아지면 성능 저하
    • 대안: 1) JOIN 사용 2) Table-Valued Parameter 사용

특징

  • 데이터 크기: 적은 데이터에 적합 (1000개 이하)
  • 성능: 데이터가 많아질수록 성능 저하
  • 사용 복잡도: 간단하게 구현 가능
  • 데이터 준비: Java에서 직접 값 전달

JOIN절

특징

  • 데이터 크기: 큰 데이터셋에 적합 (1000개 이상)
  • 성능: 성능이 상대적으로 안정적
  • 사용 복잡도: 임시테이블이나 CTE 필요
    • CTE(Commont Table Expression): WITH 구문을 사용하여 단일 쿼리 내부에서 임시로 결과를 저장해 놓고, 해당 쿼리 내에서 반복적으로 사용한는 것
  • 데이터 준비: DB에 미리 값 준비하거나 쿼리로 처리

결론

  • 실제 값을 확인해봤을 때 현재 기준 한 MD 당 3000개 이상의 업체를 가지는 케이스가 이미 존재해서, IN절은 사용하지 않기로 했다.

  • 사용 DB는 PostgreSQL 로 IN절 사용 대안으로 1) JOIN 사용 2) = ANY(ARRAY[...]) 사용이 존재했는데, JOIN절을 사용하는 것으로 결정했다.

    • PostreSQL에서 IN절은 배열처럼 처리가 되고= ANY(ARRAY[...]) 를 사용하면 배열을 효율적으로 처리할 수 있어서 IN절보다는 더 나은 성능을 얻을 수 있다고 한다. 그러나 이 또한 배열로 처리되는 것으로 대량의 데이터가 넣어질 경우 성능 저하가 발생할 수 있다.

    • 따라서 JOIN절을 사용할 경우 대량의 데이터 사용 시 실행 계획이 더 최적화될 수 있을 것으로 보였다.

    • 또한, EXPLAIN 을 사용하여 실행 계획을 살펴봤을 때 JOIN ON절 조건으로 거는 값이 인덱스를 타도록 되어 성능적으로 훨씬 좋을 것으로 보였다.

0개의 댓글