
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';

둘 다 결과는 동일하지만, 옵티마이저가 각 테이블의 카디널리티를 고려하여 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';
주석으로 각 컬럼의 의미를 기록해두면 실무에서 디버깅할 때 큰 도움이 됩니다.
참고 자료
'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 |