Programing/SQL

WHERE 절과 JOIN에서의 쿼리 순서, 정말 중요할까?

2025. 6. 30. 05:32
반응형

JOIN 순서와 WHERE 조건 순서, 성능에 영향 있을까?

SQL을 다루다 보면 자주 듣게 되는 이야기 중 하나가 "JOIN 순서나 WHERE 조건의 순서가 쿼리 성능에 영향을 준다"는 말입니다. 초보자들이 이 부분에서 혼란을 겪는 이유는, 실제로 눈으로 보이는 SQL 작성 순서와 DB 엔진 내부에서 처리되는 순서가 다르기 때문입니다.

이번 글에서는 JOIN과 WHERE 절의 순서가 정말 성능에 얼마나 영향을 주는지, 실무에서 어떤 점을 고려해야 하는지를 살펴보겠습니다.


SQL 실행 순서 이해하기

많은 개발자들이 SQL 쿼리를 작성할 때 SELECT 문을 위에서 아래로 순차적으로 읽습니다. 하지만 DB가 SQL을 처리하는 논리적 순서는 다음과 같습니다:

FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

이 순서를 "Logical Query Processing Phase"라고 부르며, 이는 논리적인 처리 순서일 뿐 실제 엔진이 데이터를 읽고 필터링하는 순서는 옵티마이저의 판단에 따라 달라질 수 있습니다.

즉, DBMS는 효율을 위해 JOIN 순서를 재배열하거나 WHERE 조건 평가 순서를 바꿀 수 있다는 것이 핵심입니다.


JOIN 순서가 미치는 영향

INNER JOIN vs OUTER JOIN

  • INNER JOIN은 어느 테이블을 먼저 조회하든 결과가 동일합니다. 하지만 처리 비용은 달라질 수 있습니다.
  • OUTER JOIN은 순서가 중요합니다. LEFT OUTER JOIN에서 왼쪽 테이블이 먼저 기준이 되므로, 쿼리 결과가 달라질 수 있습니다.

Cardinality와 쿼리 최적화

"카디널리티(Cardinality)"는 특정 조건으로 필터링했을 때 남는 데이터 건수의 수를 의미합니다. 카디널리티가 낮을수록(데이터가 적을수록) JOIN 시 부담이 적어지므로, 옵티마이저는 보통 적은 레코드를 반환하는 테이블부터 먼저 읽는 전략을 선호합니다.

실제로 순서가 중요한가?

MySQL 같은 RDBMS는 대부분 옵티마이저가 JOIN 순서를 자동으로 조정합니다. 그러나 다음과 같은 상황에서는 작성 순서가 영향을 미칠 수 있습니다:

  • FORCE INDEX, STRAIGHT_JOIN 등을 사용해 순서를 고정한 경우
  • OUTER JOIN으로 인해 테이블 순서가 논리적으로 강제되는 경우
  • 통계 정보가 부정확할 때 옵티마이저가 잘못된 계획을 선택할 수 있음

WHERE 절 순서의 오해

많은 개발자들이 WHERE 절 내 조건 순서가 쿼리 성능에 직접적인 영향을 미친다고 오해하곤 합니다.

WHERE 순서로 결과가 바뀔까?

정답은 "아니오"입니다. WHERE 조건의 순서는 논리적으로 AND 연산이기 때문에 결과를 바꾸지 않습니다. 하지만 조건별로 비용이 다를 수 있고, 옵티마이저는 더 효율적인 조건부터 먼저 평가하려 시도합니다.

실행 계획(Execution Plan)에서의 WHERE 처리

실행 계획에서 WHERE 절은 access condition 혹은 filter condition으로 나뉘어 분석됩니다. 인덱스가 활용되는 조건은 access condition으로 표시되며, 나머지는 filter 단계에서 처리됩니다.

WHERE 조건 분리 시 주의사항

  • OR 조건이 포함되면 쿼리 최적화가 어려워질 수 있습니다.
  • 서브쿼리를 사용하는 조건은 옵티마이저가 재작성하기 전까지 독립적으로 실행되기 때문에 예측과 다를 수 있습니다.

실전 예제: 순서만 바꾼 쿼리 비교

같은 조건이라도 작성 순서를 달리한 두 쿼리를 비교해보겠습니다.

예제 1: 순서 A

SELECT SQL_NO_CACHE *
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id
WHERE u.gender = 'Female' AND o.status = '1';

예제 2: 순서 B

SELECT SQL_NO_CACHE *
FROM orders o
INNER JOIN users u ON u.user_id = o.user_id
WHERE o.status = '1' AND u.gender = 'Female';

조인 순서에 따른 속도 차이를 제외하고 where 순서에 따른 속도 차이는 영향이 거의 없다.

 

둘 다 결과는 동일하지만, 옵티마이저가 각 테이블의 카디널리티를 고려하여 JOIN 순서를 재조정할 수 있습니다.

EXPLAIN으로 확인하기

EXPLAIN SELECT *
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id
WHERE u.gender = 'Female' AND o.status = '1';
  • key 컬럼: 사용된 인덱스 정보
  • rows 컬럼: 각 테이블에서 예상되는 레코드 수
  • Extra 컬럼: 추가적인 정보 (e.g., Using where)

이 정보를 통해 옵티마이저가 실제 어떤 순서로 데이터를 탐색하는지 파악할 수 있습니다.


최적화를 위한 권장 사항

결론적으로 JOIN이나 WHERE 절의 작성 순서가 반드시 성능을 결정짓는 것은 아닙니다.

  • 옵티마이저가 대부분 순서를 최적화하므로 작성 순서에 과도하게 집착할 필요는 없습니다.
  • 하지만 데이터의 분포, 카디널리티, 인덱스 활용 여부를 고려해 효율적인 조건 배치를 고민해야 합니다.
  • ORM 사용 시 쿼리 생성 로직이 옵티마이저의 자유도를 제한할 수 있으니 주의가 필요합니다.

예제 코드 정리

JOIN + WHERE 예제

SELECT u.id, u.name, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE u.gender = 'Female'
  AND o.status = '1';

EXPLAIN 해석 예시

EXPLAIN SELECT u.id, u.name, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE u.gender = 'Female'
  AND o.status = '1';

주석으로 각 컬럼의 의미를 기록해두면 실무에서 디버깅할 때 큰 도움이 됩니다.


참고 자료

  • https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
  • 속도 측정을 위한 SQL_NO_CACHE
  • Mockaroo로 대용량 테스트 데이터 쉽게 생성하기
반응형

'Programing > SQL' 카테고리의 다른 글

MySQL 날짜/시간 함수 정리 및 자주 쓰는 패턴 모음 (MySQL Date and Time Functions)  (0) 2025.07.05
GROUP BY, WHERE와 HAVING의 차이(SQL Basics Explained)  (2) 2025.07.03
Mockaroo로 대용량 테스트 데이터 쉽게 생성하기  (4) 2025.06.30
SQL :: ORACLE :: 오라클 지우기  (0) 2008.12.01
SQL :: ORACLE :: 오라클 :: 자동증가값 :: 시퀸스 :: SEQUENCE  (1) 2008.11.30
SQL :: ORACLE :: 오라클 :: 사용자 계정 생성하기  (0) 2008.11.30
SQL :: 보안 관리 :: 끄적임  (0) 2008.11.26
SQL :: ORACLE :: 휴지인스턴스  (0) 2008.11.24
'Programing/SQL' 카테고리의 다른 글
  • MySQL 날짜/시간 함수 정리 및 자주 쓰는 패턴 모음 (MySQL Date and Time Functions)
  • GROUP BY, WHERE와 HAVING의 차이(SQL Basics Explained)
  • Mockaroo로 대용량 테스트 데이터 쉽게 생성하기
  • SQL :: ORACLE :: 오라클 지우기
Dongkkase
Dongkkase
개발자로 일하면서 부딪히는 문제풀이가 누군가에게 도움이 되길 바라며
    반응형
  • Dongkkase
    정집사의 개발로그
    Dongkkase
  • 전체
    오늘
    어제
    • All (478)
      • 금융 (61)
      • Programing (295)
        • Algorithm (39)
        • API (2)
        • javascript (122)
        • CSS (8)
        • HTML (10)
        • PHP (15)
        • JAVA (27)
        • JSP (17)
        • JSP 예제 (1)
        • IOS (1)
        • Android (1)
        • Sencha Touche (1)
        • bat file, cmd (0)
        • 디버깅 (2)
        • SQL (21)
        • MS-SQL (1)
        • MySQL (13)
        • 보안 (5)
      • Server (14)
        • Docker (1)
        • Windows (9)
        • Linux (3)
        • jeus (1)
      • Database (6)
      • IT 일반 (15)
      • 리뷰 (38)
        • Book (17)
        • 제품 (2)
        • 영화 소개 (11)
        • 음악 소개 (7)
      • 잡생각 (36)
        • 회고 (3)
        • 컬럼 (4)
        • 자료실 (6)
        • 낙서장 (12)
        • 위시리스트 (2)
        • WOW (1)
        • 덕 (1)
  • 인기 글

  • 최근 댓글

  • 태그

    자바스크립트
    블로그
    JavaScript
    php
    사고 싶은 책
    js패턴
    iT's MY LiFE
    IT·컴퓨터
    읽고 싶은 책
    Java
    자바
    자바스크립트유틸
    기초
    디자인패턴
    위시리스트
    IT블로그
    SQL
    jsp
    It
    IT 관련
Dongkkase
WHERE 절과 JOIN에서의 쿼리 순서, 정말 중요할까?
상단으로

티스토리툴바