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: 단일 테이블 집계 (권장 - 참조 무결성 보장 시)¶
개선안 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) |
요약 (최종 결론)¶
- Duplicate Weedout 전략 활용: 제공된 실행 계획의
Start temporary / End temporary는 중복된 행이 결과에 포함되지 않도록 조인 단계에서 즉시 필터링함을 의미합니다. 이는 대량의 기록 중 고유 사원만 골라낼 때 매우 효율적입니다. - 리소스 효율성: 전체 결과셋을 임시 테이블에 넣고 나중에
DISTINCT를 수행하는 방식보다, 조인 과정에서 메모리 상의 체크를 통해 중복을 걷어내는 이 방식이 CPU와 메모리 사용량 측면에서 우수합니다. - 최종 제언:
- 최고의 성능: 데이터 무결성(사원 존재 여부)이 보장된다면
사원출입기록테이블만 사용하는 개선안 A가 가장 빠릅니다. - 안정적인 선택: 사원 존재 여부를 검증해야 한다면 옵티마이저가 Semi-Join으로 최적화해 주는 개선안 B가 가장 안정적이고 효율적인 선택입니다.
- 최고의 성능: 데이터 무결성(사원 존재 여부)이 보장된다면
요약¶
- 결과값의 근거 확인: 추출하려는 정보(
사원번호)가 조인하려는 양쪽 테이블에 모두 존재하고, 그중 한쪽이 PK라면 굳이 조인할 필요가 없습니다. - Covering Index 활용:
사원출입기록테이블에(출입문, 사원번호)복합 인덱스가 있다면, 테이블 풀 스캔 없이 인덱스만 읽어서(Using index) 결과를 즉시 반환할 수 있습니다.