mybatis를 사용하는 회사에서 레거시 SQL 쿼리튜닝을 진행하고 있는데
많은 작업을 해도 성능개선이 안되는 쿼리가 있는 반면에
간단하지만 효과있는 가성비가 좋은 튜닝법이 있다.
가성비 튜닝법만 블로그에 기록해두려고한다 ✍
첫번째는 UNION, UNION ALL 이다
오라클에서도 동작방식이 비슷하지만 현업쿼리를 붙여넣기도 좀 그렇고
예전에 봤던 mysql 책에 간단하게 잘 설명 되어있어서 사용 좀 하려고한다.
먼저 결론부터 말하자면 UNION ALL에는 정렬이 안들어가서 더 빠르다
옵티마이저 동작을 살펴보도록 하자
아래는 사원테이블과 Index 정보다
0. 테이블 정보
사원테이블 | |||||
사원번호 | 생년월일 | 이름 | 성 | 성별 | 입사일자 |
int | date | varchar | varchar | enum('M', 'F') | date |
PK | 사원번호 |
INDEX_1 | 입사일자 |
INDEX_2 | 성별 + 성 |
1. UNION을 사용해보자
-- 성별+성으로 사원번호 조회하는 쿼리 (UNION)
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'M'
AND 성 = 'Morton'
UNION
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'F'
AND 성 = 'Morton'
-- 실행결과
-- 성별 사원번호
M 224281
M 227462
...
M 441040
M 441161
M 442307
인덱스를 잘사용했고 데이터도 많이 없어서 실행시간이 짧다.
그러면 실행계획을 한번 볼까?
-- 해당쿼리 실행계획
explain
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'M'
AND 성 = 'Morton'
UNION
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'F'
AND 성 = 'Morton'
결과를 보면 Using temporary항목이 있다
데이터를 임시 저장소에 담았다는 것이다 (성능상 안좋다)
왜냐하면 UNION은 정렬을 한 뒤 중복제거를 한다!! 그 과정에서 temporary에 저장하는 것이다
2. UNION ALL 을 사용하여 실행계획을 보자
-- 성별+성으로 사원번호 조회하는 쿼리의 실행계획 (UNION ALL)
explain
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'M'
AND 성 = 'Morton'
UNION ALL
SELECT 'M' AS 성별,
사원번호
FROM 사원
WHERE 성별 = 'F'
AND 성 = 'Morton'
UNION ALL을 사용하니 Using temporary가 빠진 것을 볼 수 있다👍
3. 결론
모든경우는 아니지만
중복되는 데이터가 나오지 않는다면 UNION을 지향 하는 것이 좋다
테이블에 데이터가 쌓이면 쌓일 수록 이런 쿼리들이 악성쿼리가 된다
튜닝 별거 없는 것 같으면서도 별 거 있다 ㅎㅎ
뭔가 써먹을만한 내용이 있으면 블로그에 자주 써보도록 해야겠다
참고자료
현업
업무에 바로쓰는 SQL튜닝
'DB' 카테고리의 다른 글
[Oracle] Oracle Text 대량 텍스트 색인화 (feat. 상품검색기능) (0) | 2024.06.07 |
---|---|
Oracle DB 관리자 필수 가이드: 기본 쿼리로 데이터베이스 리소스 정보 확인하기 (0) | 2024.05.22 |
[MYSQL 쿼리튜닝] 파티셔닝 (1) | 2024.01.06 |
[MYSQL 쿼리튜닝] 커버링 인덱스 (2) | 2023.11.23 |