궁금증

[SQL] Join vs SubQuery: 언제, 왜, 어떻게 선택할까?

0and24 2024. 12. 9. 04:20

며칠 전, 다대다 면접에서 면접관 한 분이 저에게 물었습니다.

"혹시 조인과 서브쿼리 중 어떤 것이 성능이 더 좋나요?"

순간 잠시 생각을 한 뒤 이렇게 대답했습니다:

"많은 양의 데이터를 다루지 않는 이상 서브쿼리와 조인의 성능 차이를 알아채는 것은 어렵다고 생각합니다. 하지만, outer join처럼 테이블 간의 데이터를 결합해야 하는 경우에는 서브쿼리는 내부 함수를 사용하거나 조건문을 작성해야 해서 SQL 구조가 직관적이지 않을 수 있습니다. 이는 성능뿐만 아니라 코드의 협업 측면에서도 JOIN보다 적합하지 않다고 생각합니다."

당시에는 비교적 자신 있게 대답했지만, 며칠이 지나고 문득 궁금해졌습니다. 정말 내 대답이 옳았을까? JOIN과 서브쿼리의 차이점과 성능은 실제로 어떻게 다를까? 그래서 이번 기회에 JOIN과 서브쿼리에 대해 깊이 공부하고, 제가 배운 내용을 여러분과 나누고자 합니다.


1. 서브쿼리란 무엇인가?

정의

서브쿼리는 SQL 쿼리 내부에서 또 다른 쿼리를 중첩하여 실행하는 구조를 말합니다. 내부 쿼리(서브쿼리)가 먼저 실행되어 결과를 반환하며, 외부 쿼리가 이를 참조하여 데이터를 추출합니다.

장점

  • 간결성: 복잡한 조건을 간단히 표현할 수 있습니다.
  • 논리적 분리: 데이터를 필터링하거나 집계할 때 로직을 분리해 가독성을 높일 수 있습니다.
  • 특정 필터링 작업에 유용: 예를 들어, 평균 이상의 판매 데이터를 필터링하는 작업.

단점

  • 성능 저하 가능성: 특히 상관 서브쿼리(Correlated Subquery)의 경우 외부 쿼리의 각 행마다 서브쿼리가 실행되므로 성능이 저하될 수 있습니다.
  • 직관성 부족: 복잡한 서브쿼리는 팀 협업에서 이해하기 어려운 구조가 될 수 있습니다.
SELECT * 
FROM orders
WHERE customer_id IN (
    SELECT customer_id
    FROM customers
    WHERE is_active = true
);

위 쿼리는 customers 테이블에서 활성 고객(is_active = true)의 customer_id를 추출한 뒤, 이를 기반으로 orders 테이블에서 데이터를 필터링합니다.


2. 조인이란 무엇인가?

정의

조인은 두 개 이상의 테이블을 결합하여 연관된 데이터를 한 번에 가져오는 방법입니다. 테이블 간의 관계를 정의하여 원하는 데이터를 병합합니다.

장점

  • 성능 최적화: 데이터베이스 옵티마이저가 조인 연산을 효율적으로 처리.
  • 명확한 구조: 테이블 간 관계를 명시적으로 보여주므로 가독성이 좋습니다.
  • 대규모 데이터 처리에 적합: 데이터를 병합한 뒤 추가 처리를 수행하는 데 효과적입니다.

단점

  • 복잡성 증가 가능: 여러 테이블을 조인하면 쿼리가 복잡해질 수 있습니다.
SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE c.is_active = true;

이 쿼리는 customers와 orders 테이블을 customer_id를 기준으로 결합하고, 활성 고객의 데이터를 필터링합니다.


3. JOIN과 서브쿼리: 성능 비교

결론이라고 할 수 있는 아래는 그림1은 특정 상황(예: 데이터의 크기, 파티션의 구조, 쿼리 복잡도 등)에서 측정된 결과입니다.
다른 조건(예: 데이터베이스 엔진, 인덱스 사용 여부 등)에서는 결과가 달라질 수도 있습니다. 

그림1 출처:https://stackoverflow.com/questions/27523714/mysql-correlated-subquery-vs-join-performance

JOIN이 적합한 경우

  • 테이블 간의 관계를 병합하여 결과를 만들어야 할 때.
  • 데이터 크기가 클수록 성능 최적화 효과가 더욱 두드러집니다.
  • 예: 사용자와 주문 데이터를 조합하여 보고서를 생성.

서브쿼리가 적합한 경우

  • 특정 데이터를 필터링하거나 조건을 추가해야 할 때.
  • 집계 함수나 동적 조건을 사용해 데이터를 선별할 때.
  • 예: 평균 이상의 판매 데이터를 필터링.

성능 비교 예제

SELECT *
FROM orders
WHERE total_amount > (
    SELECT AVG(total_amount)
    FROM orders
);

 

  • 평균 판매 금액 이상의 주문 데이터를 필터링.
  • 집계 값 기준 필터링 작업에 간결.

SELECT c.customer_name, SUM(o.total_amount) AS total_spent
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_name;

 

  • customers와 orders 테이블을 결합해 고객별 총 주문 금액을 계산
  • 데이터를 병합하고 집계 결과를 도출할 때 효율적.
  •  

4. 결론: 언제 무엇을 선택할 것인가?

다대다 면접에서의 제 답변은 부분적으로 맞았지만, JOIN과 서브쿼리는 단순히 성능만으로 비교할 수 없습니다. 물론 성능만 놓고 보면 대부분의 경우 조인이 더 우수한 것이 사실이지만, 쿼리의 목적과 상황에 따라 적합한 방식을 선택해야 합니다. 두 개념의 차이를 이해하고 올바르게 활용하는 것이 중요합니다.

  • JOIN: 여러 테이블의 데이터를 결합해야 한다면 기본적으로 선택.
  • 서브쿼리: 특정 조건을 필터링하거나 집계 값을 활용할 때 적합.

이 글을 작성하며 JOIN과 서브쿼리에 대해 깊이 공부하게 되었습니다. 자료조사를 하면서 많은 사람들이 서브쿼리가 코드의 직관성이 떨어져서 선호하지 않는다고 이야기하는 것을 보았습니다. 그래서 "JOIN만 잘 알아도 충분하다"는 의견도 종종 접했는데요. 하지만 저는 이 두 가지의 차이를 명확히 알고 상황에 맞게 사용하는 것이 더 나은 선택이라고 생각합니다. 각 기술의 장단점을 이해하고 적재적소에 활용하면, 보다 효율적이고 협업하기 좋은 코드를 작성할 수 있을 것입니다.

 

참고 자료들:
https://stackoverflow.com/questions/3856164/which-of-the-join-and-subquery-queries-would-be-faster-and-why-when-i-should-pr

 

Which of the join and subquery queries would be faster and why? When I should prefer one over the other?

I have a join query Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id and a subquery query Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept) Which would be fast...

stackoverflow.com

https://www.linkedin.com/advice/0/how-do-you-decide-when-use-subquery-join-sql

 

How do you decide when to use a subquery or a join in SQL?

Learn the pros and cons of subqueries and joins in SQL, and how to decide when to use them in your database development projects.

www.linkedin.com