실무에서 데이터 조회 시 Spring JPA 및 QueryDSL을 활용하고 있는데 조회 성능이 좋게 나오지 않아 조금 더 나은 조회 성능을 위해 (이를 최적화라 부르기에는 민망했다...) QueryDSL 코드를 이것 저것 뜯어가보면서 수정을 했다.
특히 코드를 수정하고 테스트를 진행하던 중 수정 하기 전에는 데이터가 잘 나왔던 것이 수정 한 후에는 데이터가 나오지 않아 어디가 잘못 된 것인지 고민하고 끙끙 거리고 있었는데 파트원들의 집단 지성으로 문제점을 발견하였다.
지금 생각해보면 별 것 아닌 문제였는데 그 때는 왜 안보였는지 모르겠지만 조회했을 때 원인은 조회 시 Table 조인을 할 때 Table Join on이었던 것이 Table Join where로 수정되어 있었던 문제였다.
그래서 이번 포스팅으로 DB Join에 관련하여 DB 쿼리 최적화로 수정했던 2가지 내용에 대해 정리 해보고자 한다.
- Table간 Join시 Inner Join과 Left Join 후 where 하는 것은 어떤 차이가 있을까?
- Table Join on과 Join Where의 차이는 무엇일까?
일단 차이를 알아보기전 테스트 데이터는 다음과 같다.
테스트를 위해 나의 JPA와 QueryDSL 온라인 스승인 김영한센세의 예제 테이블로 진행을 해본다.
일단 Table간의 관계를 보면 Member <-> Team은 N:1이고, TEAM_ID로 FK가 구성되어 있다.
<Member Table>
<Team Table>
1. Table간 Join시 Inner Join과 Left Join 후 where 하는 것은 어떤 차이가 있을까?
Ans) 결과적으로는 조회시 차이가 없다.
답은 "결과적으로는 조회시 차이가 없다" 였다.
# LEFT JOIN, WHERE
SELECT * FROM "MEMBER" m LEFT JOIN TEAM t ON m.TEAM_ID = t.TEAM_ID WHERE t.NAME ='MANCITY';
# INNER JOIN, WHERE
SELECT * FROM "MEMBER" m INNER JOIN TEAM t ON t.TEAM_ID = m.TEAM_ID WHERE t.NAME = 'MANCITY';
두개의 쿼리를 실행했을 때 조회 값은 다음과 똑같다.
(참고: INNER JOIN ON과 INNER JOIN WHERE은 똑같은 결과가 나오는 쿼리이다.)
그럼 LEFT JOIN 하고 Where를 설정했을 때 어떤식으로 쿼리가 실행될까?
1-1) Member 테이블에 Team 테이블 LEFT JOIN
LEFT JOIN만 하는 것은 Oracle로 따지면 cartesian product라고도 하는데 M*N의 형태로 결과값이 출력된다.
Member 테이블의 12개의 칼럼, Team 테이블의 4개의 칼럼이 곱의 형태로 조회되어 총 48개의 데이터가 나오게 된다.
1-2) LEFT JOIN 할 때 Member의 TeamID값과 Team의 Team ID값이 같은 것들을 조회한다.
48개의 데이터 중에서 Member의 TeamID값과 Team의 Team ID값이 같은 것을 매핑하여 데이터를 조회한다.
이렇게 되어야 알맞은 데이터가 보여진다.
1-3) LEFT JOIN 후 팀의 이름이 'MANCITY'인 것만 조회한다.
팀의 이름이 'MANCITY'인 것을 조회하게 되면
즉
1) LEFT JOIN을 진행한다.
2) LEFT JOIN ON 그리고 Where은 조인하려는 테이블(여기서는 Team)을 모두 Member로 불러오고
3) Member의 Team Id와 Team의 Team Id값을 1차적으로 붙인 다음 Team의 이름이 'MANCITY' 인 것을 필터링 하는 것이다.
그렇다면 Inner Join으로 바로 진행하면 어떻게 그려질까
2-1) Inner Join 후 Where
1) LEFT JOIN On을 수행할 때에는 Member의 Team ID와 Team Team ID값이 같은 것들을 불러와서 하나의 집합을 구성한다음 그 집합에서 팀의 이름이 'MANCITY' 인 것을 필터링하는 것
2) INNER JOIN은 테이블 조인을 불러올 때 아예 Team ID와 Team Team ID값이 같은 것과 팀의 이름이 "MANCITY" 인 것을 불러와서 조회하는 것이다.
두 쿼리의 차이점은
Member의 Team ID와 Team Team ID값이 같은 것들을 불러와서 하나의 집합을 구성하는 부분이 차이점인데 지금은 데이터 갯수가 얼마 되지 않아 Join 성능에 큰 차이가 없겠지만 1000만건, 2000만건 많은 데이터를 가진 테이블간의 조인이라면 새롭게 하나의 집합을 구성하는 것 자체가 즉 LEFT JOIN DB쪽 조회시 INNER JOIN 보다 큰 리소스를 사용하게 된다.
여기서 깨달았던 점들은 무분별한 LEFT JOIN 후 Where이 아닌 성능을 위해서는 상황에 맞게 INNER JOIN도 써야 한다는 점이었다.
실무에서 개발하면서도 테스트 데이터만 조회해서 쿼리 속도가 줄어들었음을 아주 크게 체감하지는 못하고 있지만 약간은 조회 속도가 빨라진 것을 느낄 수 있었다.
쓰다보니 새벽 2시반,, 그리고 뭔가 길이 길어졌는데 그 다음 포스팅은 2번 LEFT JOIN ON과 LEFT JOIN WHERE의 차이점에 대해 정리할 예정이다.
그럼 끝!
'DB > DB 이해하기' 카테고리의 다른 글
[DB] Left Join on과 Where의 차이 (0) | 2021.10.10 |
---|
댓글