백엔드 개발자 블로그

5.1 SQL문 재작성으로 착한 쿼리 만들기 본문

독서/업무에 바로쓰는 SQL 튜닝

5.1 SQL문 재작성으로 착한 쿼리 만들기

backend-dev 2024. 9. 6. 14:41

조인방식, 서브쿼리 형태, 조인 조건절 등을 변경하여 튜닝해보자


처음부터 모든 데이터를 가져오는 나쁜 SQL문

1. 튜닝 전

소요 시간 2.36초

SELECT 사원.사원번호,
    급여.평균연봉
    금여.최고연봉
    급여.최저연봉
FROM 사원,
	(SELECT 사원번호, 
    	ROUND(AVG(연봉),0) 평균연봉, 
        ROUND(MAX(연봉),0) 최고연봉, 
        ROUND(MIN(연봉),0) 최저연봉
    FROM 급여
    GROUP BY 사원번호
    ) 급여
WHERE 사원.사원번호 = 급여.사원번호
AND 사원.사원번호 BETWEEN 10001 AND 10100;

 

2. 튜닝 전 실행 계획 분석

인라인 스키마 : 조건절 없이 group by -> 전체 데이터 접근

where between -> type : range : 

인라인 스키마 : select_type : DERIVED

 

3. 튜닝 

SELECT 사원.사원번호,
	(SELECT ROUND(AVG(연봉),0)
    	FROM 급여 AS 급여1
        WHERE 사원번호 = 사원.사원번호
    ) AS 평균연봉,
    (SELECT ROUND(MAX(연봉),0)
    	FROM 급여 AS 급여2
        WHERE 사원번호 = 사원.사원번호
    ) AS 최고연봉,
    (SELECT ROUND(MIN(연봉),0)
    	FROM 급여 AS 급여3
        WHERE 사원번호 = 사원.사원번호
    ) AS 최저연봉,
FROM 사원
WHERE 사원.사원번호 BETWEEN 10001 AND 10100;

 

4. 결과

소요 시간 2.36초 -> 0.00초


비효율적인 페이징을 수행하는 나쁜 SQL문

1. 튜닝전

소요 시간 0.41초

SELECT 사원.사원번호, 사원.이름, 사원.성, 사원.입사일자
FROM 사원, 급여
WHERE 사원.사원번호 = 급여.사원번호
	AND 사원.사원번호 BETWEEN 10001 AND 50000
GROUP BY 사원.사원번호
ORDER BY SUM(급여.연봉) DESC
LIMIT 150,10;

 

2. 튜닝 전 실행 계획 분석

사원 테이블에서 그룹핑과 정렬 연산 -> extra : Using temporary, Using filesort

전체 테이블을 가져온 뒤 10개만 조회하기는 비효율적

 

3. 튜닝

가져올 데이터를 최대한 줄여서 조인하자

SELECT 사원.사원번호, 사원.이름, 사원.성, 사원.입사일자
FROM (SELECT 사원번호
		FROM 급여
        WHERE 사원번호 BETWEEN 10001 AND 50000
        GROUP BY 사원번호
        ORDER BY SUM(급여,연봉) DESC
        LIMIT 150,10) 급여, 
    사원
WHERE 사원.사원번호 = 급여.사원번호

 

4. 결과

소요시간 : 0.41초 > 0.21초


필요 이상으로 많은 정보를 가져오는 나쁜 SQL문

1. 튜닝전

소요 시간 0.15초

SELECT COUNT(사원번호) AS 카운트
FROM (SELECT *
		FROM (SELECT * 
        		FROM 사원
                WHERE 성별 = 'M'
                	AND 사원번호 > 300000
            ) 사원
        LEFT JOIN 부서관리자
        	ON 사원.사원번호 = 부서관리자.사원번호
        ) 서브쿼리 ;

 

2. 튜닝 전 실행 계획 분석

외부 조인의 경우 드리븐 테이블은 있어도 되고 없어도 되는 역할을 수행

 

3. 튜닝

외부 조인을 없앰

SELECT COUNT(사원번호) AS 카운트
FROM 사원
WHERE 성별 = 'M'
	AND 사원번호 > 300000;

 

4. 결과

소요 시간 : 0.15초 > 0.05초


대량의 데이터를 가져와 조인하는 나쁜 SQL문

1. 튜닝 전

SELECT DISTINCT 매핑.부서번호
FROM 부서관리자 관리자,
	부서사원_매핑 매핑
WHERE 관리자.부서번호 = 매핑.부서번호
ORDER BY 매핑.부서번호

 

2. 튜닝 전 실행 계획 분석

중복이 제거된 부서번호 열만 조회

부서번호 열로 내부 조인

부서번호가 같은지 일일이 확인하는 과정이 필요 없는 과정임

 

 

3. 튜닝

둘 중 하나의 테이블은 단순히 부서번호가 존재하는 여부만 판단

SELECT 매핑.부서번호
FROM (SELECT DISTINCT 부서번호 
		FROM 부서사원_매핑 매핑
    ) 매핑
WHERE EXISTS (SELECT 1
				FROM 부서관리자 관리자
                WHERE 부서번호 = 매핑.부서번호)
ORDER BY 매핑.부서번호

 

4. 결과

소요시간 1.2 > 0초