IN 절 vs EXISTS 절 – 조건은 같아도 성능은 다르다

Posted by heoncode
2025. 4. 12. 22:13 SQL 기초 정리
728x90
반응형
SMALL

IN과 EXISTS는 둘 다 서브쿼리를 사용하는 조건절로, 결과적으로 같은 데이터를 반환할 수 있지만 내부 동작 방식과 성능 차이로 인해 상황에 따라 적절한 선택이 필요합니다.

1. IN 절과 EXISTS 절의 기본 사용법

IN 절 예시:

SELECT name
FROM employee
WHERE department_id IN (
    SELECT id
    FROM department
    WHERE region = '서울'
);

EXISTS 절 예시:

SELECT name
FROM employee e
WHERE EXISTS (
    SELECT 1
    FROM department d
    WHERE d.id = e.department_id
    AND d.region = '서울'
);

위 두 쿼리는 동일한 결과를 반환하지만, 내부적으로 처리하는 방식은 전혀 다릅니다.

2. 내부 동작 방식의 차이

  • IN은 서브쿼리 결과를 메모리에 모두 로드하고, 메인 쿼리의 비교 값을 그 목록과 매칭합니다.
  • EXISTS는 서브쿼리가 조건을 만족하는 레코드가 하나라도 존재하는지 확인하는 방식으로, 참(True)이 되는 순간 바로 반환됩니다.

즉, EXISTS는 조건을 만족하는 레코드를 찾자마자 종료되는 반면, IN은 전체 리스트를 끝까지 확인하는 구조입니다.

3. 성능 차이 – 언제 어느 걸 쓰는 게 좋을까?

  • 서브쿼리의 결과가 매우 많은 경우 → EXISTS가 더 유리한 경우가 많습니다.
  • 서브쿼리의 결과가 작고 명확한 리스트라면 IN이 더 직관적이고 성능상 문제가 없습니다.
  • 서브쿼리에 NULL이 포함될 가능성이 있다면 EXISTS를 쓰는 것이 안전합니다.

4. 실무 팁

  • Oracle에서는 IN과 EXISTS의 성능 차이가 DB 버전이나 옵티마이저 설정에 따라 달라질 수 있으므로, 항상 실제 실행 계획(EXPLAIN PLAN)을 통해 비교하는 것이 가장 정확합니다.
  • WHERE 절 내 조건의 순서가 성능에 미치는 영향도 함께 고려해 조합적으로 테스트하는 습관이 필요합니다.

IN과 EXISTS는 비슷해 보이지만 그 사용 방식과 성능은 꽤 다릅니다. 단순히 동작만 이해할 것이 아니라, 각 조건의 구조와 서브쿼리 특성에 맞춰 쿼리를 작성해야 최적화된 결과를 얻을 수 있습니다.

#SQL기초 #IN절 #EXISTS절 #SQL서브쿼리 #SQL성능비교 #쿼리최적화

728x90
반응형
LIST

LIKE 연산자의 와일드카드(%, _) 정확히 알고 쓰기

Posted by heoncode
2025. 4. 12. 16:01 SQL 기초 정리
728x90
반응형
SMALL

LIKE 연산자는 SQL에서 문자열 패턴을 검색할 때 자주 사용되는 조건입니다. 특히 %_ 와 같은 와일드카드(wildcard) 문자를 적절히 활용하면 유연한 문자열 검색이 가능합니다. 그러나 이러한 와일드카드의 의미를 명확히 이해하지 못하면, 원하지 않는 결과를 얻을 수 있습니다.

1. 와일드카드 종류와 의미

LIKE 조건에서 사용 가능한 와일드카드는 다음과 같습니다:

  • %: 길이에 상관없이 모든 문자열을 의미합니다. 0자 이상.
  • _: 임의의 한 글자를 의미합니다.

예시:

SELECT * FROM employee
WHERE name LIKE '김%';

→ 이름이 '김'으로 시작하는 모든 직원 검색

SELECT * FROM employee
WHERE name LIKE '_현우';

→ 앞에 어떤 한 글자가 있고, 뒤에 '현우'가 오는 이름 검색 (예: '이현우', '박현우')

2. 실제 사용 예시

다음은 %_를 함께 사용하는 예시입니다:

SELECT * FROM product
WHERE code LIKE 'A__%';

→ 'A'로 시작하고, 그 뒤에 정확히 두 글자가 있으며, 그 이후에 문자열이 이어지는 상품 코드 검색

3. ESCAPE 문자를 활용한 예외 처리

만약 검색하려는 문자열에 %_가 포함되어 있다면, 이를 문자 그대로 검색하기 위해 ESCAPE 절을 사용할 수 있습니다.

SELECT * FROM memo
WHERE content LIKE '%!%%' ESCAPE '!';

→ 메모 내용에 실제 % 문자가 포함된 항목 검색

4. 주의할 점

  • %는 넓은 범위의 검색을 유도하기 때문에, 인덱스를 잘 타지 않습니다.
  • 문자열 앞에 %가 오면 인덱스 미사용이 될 가능성이 높습니다.
  • 성능 최적화가 중요한 상황에서는 가급적 LIKE 조건 대신 FULLTEXT 검색이나 정규표현식 등을 사용하는 것이 유리할 수 있습니다.

SQL에서 LIKE 연산자를 단순히 ‘포함 조건’ 정도로만 이해하고 사용하는 경우가 많습니다. 하지만 와일드카드의 특성과 인덱스 영향까지 고려하면 보다 정확하고 성능 좋은 쿼리를 작성할 수 있습니다.

#SQL기초 #LIKE연산자 #SQL와일드카드 #문자열검색 #SQL쿼리팁

728x90
반응형
LIST

CTE(Common Table Expressions)의 활용법 – 서브쿼리보다 명확한 쿼리 작성

Posted by heoncode
2025. 4. 12. 11:49 SQL 기초 정리
728x90
반응형
SMALL

SQL에서 복잡한 쿼리를 작성할 때, 서브쿼리로만 해결하기 어려운 경우가 많습니다. 이럴 때 CTE (Common Table Expressions), 즉 WITH 구문을 사용하면 쿼리의 가독성과 유지보수를 크게 향상시킬 수 있습니다.

CTE의 기본 구조

CTE는 쿼리 상단에 WITH 절로 정의하며, 마치 임시 테이블처럼 재사용할 수 있습니다. 기본 구조는 다음과 같습니다.

WITH cte_name AS (
    SELECT ... FROM ...
)
SELECT * FROM cte_name;

첫 번째 부분에서 cte_name 이라는 이름의 CTE를 정의하고, 이후 메인 쿼리에서 이를 참조합니다.

CTE 사용의 장점

  1. 가독성 향상
    복잡한 로직을 여러 단계로 나누어 각각의 CTE로 정의하면, 전체 쿼리의 흐름을 한눈에 파악할 수 있어 디버깅과 협업에 유리합니다.

  2. 재사용성
    한 번 정의한 CTE를 메인 쿼리 내에서 여러 번 사용할 수 있으므로, 같은 로직을 반복 작성할 필요가 없습니다.

  3. 재귀 쿼리 작성
    CTE는 재귀적 호출을 지원하여, 계층적 데이터(예: 조직도나 카테고리 구조)를 쉽게 처리할 수 있습니다.

실무 예시: 고객별 최근 주문 내역과 누적 주문 수

아래 예시는 고객 테이블과 주문 테이블을 기반으로, 각 고객의 최근 주문 날짜와 누적 주문 수를 CTE로 먼저 계산한 후, 이를 메인 쿼리에서 결합하는 예시입니다.

WITH order_summary AS (
    SELECT customer_id,
           COUNT(*) AS total_orders,
           MAX(order_date) AS last_order_date
    FROM orders
    GROUP BY customer_id
)
SELECT c.customer_id, c.name,
       o.total_orders, o.last_order_date
FROM customers c
LEFT JOIN order_summary o ON c.customer_id = o.customer_id;

이 쿼리는 주문 집계 로직을 별도로 분리하여, 고객 테이블과 조인할 때 단순하게 결과를 얻을 수 있습니다.

마무리

CTE(Common Table Expressions)는 복잡한 쿼리를 구조화하고 가독성을 높이는 데 매우 유용한 도구입니다. 서브쿼리로 얽힌 코드를 단순화하고, 재사용 가능한 형태로 구현할 수 있으므로, 실무에서 적극 활용하는 것이 좋습니다.

#SQL #CTE #WITH구문 #공통테이블표현 #쿼리최적화 #SQL기초 #실무팁 #데이터베이스

728x90
반응형
LIST