일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 노마드코더
- 오류
- eclipse
- 프로그래밍
- 주니어 개발자
- Spring
- 이클립스 오류
- 라이브러리
- Java
- 이클립스
- HTML
- Nomad coders
- 마이플랫폼 오류
- 여성 개발자
- 입문
- css
- 스프링 오류
- MVC
- spring 게시판
- 워드프레스 검색
- tomcat
- maven
- 스프링프레임워크
- 넥사크로 그리드
- 자바
- 톰캣 오류
- 개발자 되는 법
- android studio
- 넥사크로
- 안드로이드 스튜디오
Archives
- Today
- Total
개발초보의 Study-log
[SQL 쿼리 속도] JOIN 조건 추가보다 UNION ALL이 빠를 수 있다 본문
*MSSQL 기준
공부배경
새로 유지보수를 맡게 된 메뉴의 프로시저를 분석하는데 프로시저가 너무 길고 읽기 복잡했다.
일단 처음부터 끝까지 분석해 프로시저의 전반적인 내용은 다 파악했다.
그 다음으로 사수에게 반영을 제안할만한 리팩토링 방법을 찾아보기로 했다.
프로시저에 INNER JOIN 조건만 다른 쿼리 두 개가 UNION ALL 되어 있는 부분이 있었다.
쿼리 한 개에 조인 조건을 몰아넣어 주고 UNION ALL을 없애 코드 길이를 줄여봤다.
1. UNION ALL을 쓴 쿼리
- 쿼리 길이 51줄 / 실행속도 평균 약 0.58초
SELECT
CASE
WHEN B.AA IS NULL
OR B.AA = 'aa'
THEN '1'
ELSE '2'
END AS TYPE ,
A.BB ,
A.CC ,
A.DD ,
(
CASE
WHEN A.TIME <= '0800'
THEN CONVERT(INT,A.TIME) + '2400'
ELSE A.TIME
END
) AS TIME_FOR_CAL
FROM TABLE_1 A
INNER JOIN VIEW_1 V
ON (V.SEQ = '123' AND V.NUM = '123'+'_'+ A.ID) -- SEQ가 123
AND V.STATUS = '9'
LEFT OUTER JOIN TABLE_2 B
ON B.DATE = A.DATE
WHERE DATE BETWEEN @FROMDATE AND @TODATE
UNION ALL
SELECT
CASE
WHEN B.AA IS NULL
OR B.AA = 'aa'
THEN '1'
ELSE '2'
END AS TYPE ,
A.BB ,
A.CC ,
A.DD ,
(
CASE
WHEN A.TIME <= '0800'
THEN CONVERT(INT,A.TIME) + '2400'
ELSE A.TIME
END
) AS TIME_FOR_CAL
FROM TABLE_1 A
INNER JOIN VIEW_1 V
ON (V.SEQ = '456' AND V.NUM = '456'+'_'+ A.ID) -- SEQ가 456
AND V.STATUS = '9'
LEFT OUTER JOIN TABLE_2 B
ON B.DATE = A.DATE
WHERE DATE BETWEEN @FROMDATE AND @TODATE
2. UNION ALL 대신 INNER JOIN 조건을 추가한 쿼리
- 쿼리 길이 26줄 / 실행속도 평균 약 0.75초
SELECT
CASE
WHEN B.AA IS NULL
OR B.AA = 'aa'
THEN '1'
ELSE '2'
END AS TYPE ,
A.BB ,
A.CC ,
A.DD ,
(
CASE
WHEN A.TIME <= '0800'
THEN CONVERT(INT,A.TIME) + '2400'
ELSE A.TIME
END
) AS TIME_FOR_CAL
FROM TABLE_1 A
INNER JOIN VIEW_1 V
ON ((V.SEQ = '123' AND V.NUM = '123'+'_'+ A.ID) -- SEQ가 123
OR
(V.SEQ = '456' AND V.NUM = '456'+'_'+ A.ID)) -- SEQ가 456
AND V.STATUS = '9'
LEFT OUTER JOIN TABLE_2 B
ON B.DATE = A.DATE
WHERE DATE BETWEEN @FROMDATE AND @TODATE
결론
조인 조건이 많은 쿼리 하나를 돌리는 것보다
조인 조건이 적은 쿼리 두 개를 UNION ALL하여 돌리는 것이 더 빠를 수 있다.
테스트에서 조회된 레코드는 44줄이었는데,
실제 사용 시에는 더 많은 데이터를 불러오는 경우가 대부분이라 속도 차가 더 클 것이다.
읽기 쉬운 코드가 항상 효율적인 코드는 아니라는 건 알고 있었는데,
테스트 해보며 직접 눈으로 확인하니 공부가 됐다.
추가내용 / 2021.7.20
조인에 OR 조건이 추가되더라도
UNION ALL 대신 적절한 인덱스를 사용하는 것이 더 빠를 수 있다고 한다.
'SQL' 카테고리의 다른 글
[분석해 보세요] 결과값이 뭘까? (0) | 2021.05.18 |
---|---|
[Oracle/Tibero] 특정연도부터 올해까지의 목록 출력 (0) | 2020.07.23 |
[Oracle/Tibero] 콤보에 '전체' 추가해서 기본값으로 세팅하기 (0) | 2020.07.23 |
[MSSQL] ISNULL의 기초 이해 (0) | 2020.06.26 |
[MSSQL] 검색 조건에 LIKE와 컬럼명을 이용하는 쿼리문 (0) | 2020.04.17 |