
필자가 기획한 조인 시리즈의 마지막 주인공은 해시 조인이다
일반적으로 해시 조인은 다른 조인들에 비해 비교적 좋은 성능을 보인다고 알려져
NL 조인과 소트 머지 조인 대신 무분별하게 사용하는 케이스가 종종 있는 바로 그 해시 조인이다
그럼 해시조인이 빠르다는 얘기는 과연 사실이고, 무분별하게 사용해도 괜찮을까??
해시조인이 빠른 건 사실이지만 필자는 해시 조인을 무분별하게 사용하는 건 추천하지 않는다
위 내용을 정확히 알려면 해시 조인이 어떻게 동작하는지 그 매커니즘을 알아야 한다
이번에도 A 테이블과 B 테이블이 조인하는 경우를 예시로 들어보자 (A= Driving, B= Innier. A.id = B.A_id)
- A 테이블과 B 테이블 중 더 작은 테이블(Build Input) 을 해시 테이블로 생성한다
- A 테이블과 B 테이블 중 더 큰 테이블(Probe Input) 이 1번에 사용된 해시 함수를 이용해 해시 테이블을 순회한다
해시조인의 동작 매커니즘은 꽤나 심플하다
정리하면 조인에 참여하는 두 테이블 중 작은 테이블로 해시 테이블을 만들고, 큰 테이블로 해시 테이블을 순회한다
해시 테이블은 PGA의 Hash Area에 생성하기에 인덱싱과 버퍼캐시 히트율에 영향을 많이 받는 NL 조인보다 성능이 좋은 것은 얼추 짐작이 가능하다
그렇다면 같은 PGA 영역을 사용하고, 조인 메커니즘도 비슷한 소트 머지 조인에 비해 해시 조인이 빠른 이유는 무엇일까?
두 조인 방식의 성능에 가장 유의미한 영향을 미치는 것 중 하나는 바로 Temp TableSpace 사용 여부이다
소트 머지 조인은 조인에 필요한 두 집합을 무조건 Sorting 하기에 둘 중 하나의 테이블이라도 그 양이 많으면
바로 Temp TableSpace를 사용하게 된다
반면에 해시 조인의 경우 둘 중 하나의 테이블이 크다고 해도, 작은 테이블을 Build Input으로 선택하기에
Temp TableSpace를 사용하지 않을 수 있다.
물론 해시 조인도 두 테이블 모두 Temp TableSpace를 사용해야 할 만큼 크다면 그건 어쩔 수 없지만
설령 그렇다 해도 해시 조인이 다른 조인 방식에 비해 빠른 것은 부정할 수 없다
그렇다면 해시 조인 시 해시 테이블엔 조인 컬럼만을 저장할까?
정답은 아니다
해시 테이블에는 조인 컬럼은 물론이고, 조인에 필수적으로 사용되는 또 다른 컬럼들을 모두 저장한다
그 이유는 해시 조인의 동장 배경을 알고 있다면 쉽게 유추할 수 있다
해시 조인은 Random Access가 빈번하게 일어나는 NL 조인의 한계를 극복하기 위해 탄생했는데
해시 테이블에 조인에 필요한 정보가 포함되어 있지 않다면, 결국 NL 조인과 마찬가지로 Random Access로 데이터를 불러와야 한다
지금까지 설명한 내용을 바탕으로 곰곰이 생각해 보면
그냥 웬만하면 해시조인 쓰면 되는 거 아니야?라는 생각이 머릿속을 잠식할 수 있다
하지만 소트 머지 조인에서 한 번 설명했듯
PGA에 해시 테이블을 생성하고 소멸하는 해시 조인의 메커니즘 상
100개의 프로세스에서 해당 쿼리를 수행한다면 해시 테이블은 100개가 생성되고 소멸될 것이다
이는 시스템 리소스의 상당한 비효율을 초래한다
그러한 이유로 필자는 다음과 같이 제안한다
- 해시 조인은 조인 데이터양이 많고, 빈도수가 적을 때 사용하자
- 조인 컬럼이 등치(=) 조건일 땐 해시 조인을 사용하고, 등치 조건이 아닐 땐 소트 머지 조인을 사용하자
- 해시 조인이던 소트 머지 조인이던 NL 조인과 성능이 비슷하거나 조금 더 성능이 좋다면 그냥 NL 조인을 사용하자
'개발 > Database' 카테고리의 다른 글
[Join Series] 2. Sort Merge Join (0) | 2025.03.28 |
---|---|
[Join Series] 1. NL Join (Nested Loop) (0) | 2025.03.22 |
[Join Series] 매번 눈에 밟히는 그 조인 시리즈 (0) | 2025.03.18 |
RDB 성능 개선하기 - BETWEEN vs LIKE (0) | 2025.03.08 |
[Spring/Postgres] SKIP Lock 사용하여 동시성 이슈 해결하기 (0) | 2025.03.01 |
댓글