콘텐츠로 이동

SQL Tuning Report: 불필요한 조인 제거를 통한 성능 개선

1. Analysis Overview

대상 쿼리

EXPLAIN
SELECT COUNT(DISTINCT 사원.사원번호) AS 데이터건수
  FROM 사원,
       (SELECT 사원번호
          FROM 사원출입기록 기록
         WHERE 출입문 = 'A') 기록
 WHERE 사원.사원번호 = 기록.사원번호;

실행 계획 (EXPLAIN) 결과

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE 기록 ref I_출입문 I_출입문 4 const 526,620 Using where; Using index
1 SIMPLE 사원 eq_ref PRIMARY PRIMARY 4 tuning.기록.사원번호 1

2. Performance Diagnosis

⚠️ 주요 문제점

  • 불필요한 조인 수행: COUNT(DISTINCT 사원번호)를 구하는 것이 목적이라면, 사원출입기록 테이블만으로도 결과를 얻을 수 있습니다. 현재는 사원 테이블과 52만 번의 eq_ref 조인을 수행하고 있어 불필요한 I/O가 발생합니다.
  • 데이터 중복 접근: 사원출입기록에서 'A' 출입문을 이용한 사원번호가 52만 건(rows: 526,620) 추출됩니다. 이 52만 건 모두에 대해 사원 테이블의 PK를 탐색한 뒤, 최종적으로 DISTINCT 연산을 통해 중복을 제거하고 있습니다.
  • 리소스 낭비: 사원 테이블에 반드시 존재해야 하는 사원(참조 무결성)이라면, 사원 테이블 접근 자체가 무의미한 비용입니다.

3. Optimization Strategy

💡 쿼리 리팩토링 제안

가장 권장하는 방식은 조인 대상인 사원 테이블을 제거하는 것이지만, 만약 사원 테이블에 실제로 등록된 사원인지 반드시 검증해야 하는 비즈니스 로직이 있다면 아래의 두 가지 대안을 고려할 수 있습니다.

개선안 A: 단일 테이블 집계 (권장 - 참조 무결성 보장 시)

SELECT COUNT(DISTINCT 사원번호) AS 데이터건수
  FROM 사원출입기록
 WHERE 출입문 = 'A';

개선안 B: 사원 테이블 중심의 EXISTS (Semi-Join 최적화)

중복 제거(DISTINCT) 부하를 옵티마이저의 최적화 기능에 맡기는 방식입니다.

SELECT COUNT(1) AS 데이터건수
  FROM 사원
 WHERE EXISTS (SELECT 1
                 FROM 사원출입기록 기록
                WHERE 출입문 = 'A'
                  AND 기록.사원번호 = 사원.사원번호);

4. Expected Impact

지표 개선 전 (Join + DISTINCT) 최종 개선안 (EXISTS/Semi-Join)
작업 방식 모든 조인 결과 생성 후 중복 제거 Duplicate Weedout (중복 즉시 제거)
Extra Using where; Using index Start temporary; End temporary
최적화 기법 일반 조인 (Join) 세미 조인 (Semi-Join)

요약 (최종 결론)

  1. Duplicate Weedout 전략 활용: 제공된 실행 계획의 Start temporary / End temporary는 중복된 행이 결과에 포함되지 않도록 조인 단계에서 즉시 필터링함을 의미합니다. 이는 대량의 기록 중 고유 사원만 골라낼 때 매우 효율적입니다.
  2. 리소스 효율성: 전체 결과셋을 임시 테이블에 넣고 나중에 DISTINCT를 수행하는 방식보다, 조인 과정에서 메모리 상의 체크를 통해 중복을 걷어내는 이 방식이 CPU와 메모리 사용량 측면에서 우수합니다.
  3. 최종 제언:
    • 최고의 성능: 데이터 무결성(사원 존재 여부)이 보장된다면 사원출입기록 테이블만 사용하는 개선안 A가 가장 빠릅니다.
    • 안정적인 선택: 사원 존재 여부를 검증해야 한다면 옵티마이저가 Semi-Join으로 최적화해 주는 개선안 B가 가장 안정적이고 효율적인 선택입니다.

요약

  • 결과값의 근거 확인: 추출하려는 정보(사원번호)가 조인하려는 양쪽 테이블에 모두 존재하고, 그중 한쪽이 PK라면 굳이 조인할 필요가 없습니다.
  • Covering Index 활용: 사원출입기록 테이블에 (출입문, 사원번호) 복합 인덱스가 있다면, 테이블 풀 스캔 없이 인덱스만 읽어서(Using index) 결과를 즉시 반환할 수 있습니다.