4.3 해시 조인
- NL 조인은 인덱스를 이용한 조인으로 인덱스 구성에 따른 성능차이가 심하고, 랜덤I/O 로 인해 대량 데이터 처리에 불리하고, 버퍼캐시 히트율에 따라 성능이 들쭉날쭉하다.
- 소트 머지 조인과 해시 조인은 조인 과정에 인덱스를 사용하지 않아 대량 데이터 조인시 훨씬 빠르고 일정한 성능을 보인다.
- 소트 머지 조인은 양쪽 테이블을 정렬하는 부담이 있지만 해시 조인은 한쪽만 해시 테이블을 만들기 때문에 그런 부담이 없다.
4.3.1 기본 메커니즘
해시 조인(Hash Join)
1. Build 단계 : 작은 쪽 테이블(Build Input)을 읽어 해시 테이블(해시 맵)을 생성한다.
2. Probe 단계 : 큰 쪽 테이블(Probe Input)을 읽어 해시 테이블을 탐색하면서 조인한다.
- 해시 조인은
use_hash
힌트로 유도한다.
SELECT
...
FROM 사원 e, 고객 c
WHERE c.관리자사원번호 = e.사원번호
AND e.입사일자 >= '19960101'
AND e.부서코드 >= 'Z123'
AND c.최종주문금액 >= 20000
- 사원테이블을 읽어 해시 테이블을 생성한다,
- 이때 조인컬럼인 사원번호를 해시 테이블 키 값으로 사용한다.
- 사원 번호를 해시함수 키값으로 해시 체인을 찾고, 그 해시 체인에 데이터를 연결한다.
- 해시 테이블은 PGA 영역에 할당된 Hash Area 에 저장한다.
- 해시 테이블이 너무 큰 경우 Temp 테이블스페이스에 저장한다.
SELECT
...
FROM 사원
WHERE 입사일자 >= '19960101'
AND 부서코드 >= 'Z123'
- 고객 데이터를 하나씩 읽어 앞에서 만든 해시 테이블을 탐색한다.
- 관리사원번호(조인컬럼)을 해시 함수에 입력해 반환된 값으로 해시 체인을 착고 스캔하여 같은 사원번호를 찾는다. 찾으면 조인 성공, 없으면 실패.
SELECT
...
FROM 고객
WHERE 최종주문금액 >= 20000
4.3.2 해시 조인이 빠른 이유
- 조인 방식은 NL 조인과 거의 동일하다.
- PGA 영역을 사용하고, 해시 조인은 래치 획득 과정이 없어 NL 보다 빠르다.
- 해시 조인도 Build Input 과 Probe Input 각 테이블을 읽을 때 DB 버퍼캐시를 경유하고 인덱스를 이용하기도 한다.
소트 머지 조인 vs 해시 조인
- 소트 머지 조인은 양쪽 집합을 정렬해야 한다.
- 둘중 어느 하나가 중대형이라면 Temp 테이블스페이스, 즉 디스크에 쓰는 작업을 수반한다.
- 해시 조인은 어느
한쪽
을 읽어 해시 맵을 만든다.
- 둥 중 작은 집합을 해시 맵 Build Input 으로 선택하므로 두 집합 모두 Temp 로 갈정도로 크지 않는 한 Temp 즉 디스크 작업은 없다.
- 따라서 인메모리(In-Memory) 해시 조인이 가장 효과적이다.
- 설령 Temp 를 써도 대량 데이터 조인시 일반적으로 해시 조인이 가장 빠르다
- 두 테이블 모두 대용량으로 인메모리 해시조인이 불가능한 경우 분할 정복 방식으로 DBMS 는 해시조인 처리한다.
1. 파티션 단계
- 조인하는 양쪽 집합의 조인 컬럼에 해시 함수를 적용하고 반환된 해시 값에 따라 동적으로 파티셔닝한다.
- 파티셔닝 된 양쪽 집합을 디스크 Temp 공간에 저장하므로 인메모리 해시 조인보다는 성능이 많이 떨어진다.
2. 조인 단계
- 각 파티션 짝에 대해 조인이 수행된다.
- 이때 각각에 대한 Build Input 과 Probe Input 은 독립적으로 결정된다.
- 즉 작은쪽을 Build Input 으로 선택하고 진행된다.
4.3.4 해시 조인 실행계획 제어
위쪽(HASH JOIN 바로 아래) 사우너 데이터(Build Input) 로 해시 테이블을 생성한 후, 아래쪽 고객 테이블(Probe Input)에서 읽은 조인 키값으로 해시 테이블을 탐색하면서 조인한다
고 해색하면 된다.(위쪽 Build Input 과 아래쪽 Probe Input 을 읽을 떄 인덱스를 이용한 사실도 실행계획에서 확인가능한다 물론 Table Full Scan 도 가능)
HASH JOIN
TABLE ACCESS (BY INDEX ROWID) OF '사원' TABLE
INDEX (RAGNE SCAN) OF '사원_X1' (INDEX)
TABLE ACCESS (BY INDEX ROWID) OF '고객' TABLE
INDEX (RAGNE SCAN) OF '고객_X1' (INDEX)
use_hash
힌트만 사용시 옵티마이저가 카디널리티가 작은 테이블을 일반적으로 선택
- 직접 선택하고 싶은 경우
leading
이나 ordered
힌트를 사용하면 된다.
세 개 이상 테이블 해시 조인
A,B,C 조인시 A<->B<->C
방식으로 조인하면 된다.
leading
힌트로 지정시 leading
의 첫번째 파라미터로 지정한 테이블은 무조건 BUild Input 으로 선택된다.
- 가능한 패턴은 2가지이다.
- 변경 하고 싶은 경우
swap_join_inputs
힌트를 사용하라
- 조인한 결과집합을 Build Input 으로 사용하고 싶은 경우
no_swap_join_inputs
힌트를 사용하라
4.3.5 조인 메소드 선택 기준
- 반드시 선택에는 이유와 근거를 가지고 해야 한다.
- 소량 데이터 조인 : NL 조인
- 대량 데이터 조인 : 해시 조인
- 대량 데이터 조인인데 해시 조인으로 처리할 수 없을 때, 즉 도인 조건식이 등치(=)조건이 아닐때(조인 조건식이 아예 없는 카테시안 곱 포함) : 소트 머지 조인
- (최적화된) NL 조인과 해시 조인 성능이 같은 경우 : NL 조인
- 해시 조인이 약간 더 빨라도 : NL 조인
- NL 조인보다 해시 조인이 매우 빠른 경우 : 해시 조인
- NL 조인에 사용하는 인덱스는 영구적으로 유지하면서 다양한 쿼리를 위해 공유 및 재사용하는 자료구조이다
- 해시 테이블은 단 하나의 쿼리를 위해 생성하고 조인이 끝나면 곧바로 소멸하는 자료구조이다.
- 따라서 수행시간이 짧으면서 수행빈도가 매우 높은 쿼리(OLTP) 를 해시 조인으로 처리하면 CPU 와 메모리 사용률리 증가하고 여러 해치 경합이 발생가능하다.
- 다음 조건시 해시 조인을 사용해라
- 수행 빈도가 낮고
- 쿼리 수행 시간이 오래 걸리는
- 대량 데이터 조인할 때
- 이 세가지 조건은 배치프로그램, DW, OLAP 성 쿼리의 특징이다.