불필요한 조인을 수행하는 나쁜 SQL 문
현황 분석
| 튜닝 전 실행 계획 |
FROM 절에서 사원 테이블과 사원출입기록 테이블로 작성한 인라인 뷰를 사원번호 열로 내부 조인하는 쿼리
즉, A출입문으로 출입한 사원이 총 몇 명인지 구하는 쿼리
EXPLAIN
SELECT COUNT(DISTINCT 사원.사원번호) as 데이터건수
FROM 사원,
(SELECT 사원번호
FROM 사원출입기록 기록
WHERE 출입문 = 'A') 기록
WHERE 사원.사원번호 = 기록.사원번호;
- SQL문 결과 : 총 1건의 결과 출력(데이터 건수 150000), 359 ms 소요
- id 둘다 1 → 조인 수행
- 드라이빙 테이블인 사원출입기록 테이블은 I_출입문 인덱스 활용하여 A 출입문에 관한 기록이 있는 사원번호를 구함
- WHERE 절에서 값이 'A' 인 상수와 직접 비교하므로 ref 항목이 const로 출력, 인덱스를 사용한 동등(=) 비교 수행 (type 항목 : ref)
- 드리븐 테이블인 사원 테이블은 기본 키 (key 항목 : PRIMARY)를 사용해서 조인 조건절인 사원번호 열로 데이터 비교
- type 항목 : eq_ref → 드리븐 테이블에서 기본 키를 사용
튜닝 수행
SELECT COUNT(DISTINCT 사원.사원번호) as 데이터건수
FROM 사원,
사원출입기록 기록
WHERE 사원.사원번호 = 기록.사원번호
AND 출입문 = 'A';
- FROM 절의 인라인 뷰는 옵티마이저에 의해 조인 방식이 뷰 병합(view mergind)으로 최적화되어 위 SQL문처럼 수행
- 드라이빙 테이블인 사원출입기록 테이블에 접근할 때 I_출입문 인덱스를 활용하여 데이터에 접근
- SELECT 절의 최종 결과 : 사원 테이블의 사원번호에서 중복 제거한 건수를 구한 것
- 실제로는 66만여 건에 달하는 사원출입기록 테이블의 데이터 결과가 최종 결과에 어떻게 활용되는지 확인 필요
- 사원출입기록 테이블의 사원번호는 사원 테이블과 조인을 수행하는 과정 중에 값의 존재 여부만 알면 되기 때문
DESC 사원;
튜닝 결과
| 튜닝 후 실행 계획 |
사원출입기록 테이블의 데이터는 최종 결과에 사용하지 않고 단지 존재 여부만 파악하면 되므로 EXISTS 구문으로 변경
출입문 A에 관한 기록이 있는 사원번호에 대해 조인을 수행한 뒤, 해당하는 데이터만 집계하는 방식으로 튜닝
EXPLAIN
SELECT COUNT(1) as 데이터건수
FROM 사원
WHERE EXISTS (
SELECT 1
FROM 사원출입기록 기록
WHERE 출입문 = 'A'
AND 기록.사원번호 = 사원.사원번호
);
- 359 ms → 179ms (속도 개선)
- id가 1인 테이블 항목에 먼저 출력된 사원 테이블은 드라이빙 테이블이고, <subquery2>는 드리븐 테이블
- <subquery2>는 id가 2인 사원출력기록 테이블로서, 사원출력기록 테이블은 EXISTS연산자로 데이터 존재여부를 파악하기 위해 임시테이블을 생성하는 MATERIALIZED로 표기
* 참고
'SQL 튜닝 > 테이블 조인 설정 변경' 카테고리의 다른 글
[SQL 튜닝] 메인 테이블에 계속 의존하는 나쁜 SQL 문 (0) | 2023.07.20 |
---|---|
[SQL 튜닝] 작은 테이블이 먼저 조인에 참여하는 나쁜 SQL 문 (0) | 2023.07.19 |
댓글