해시 조인

운구름·2022년 7월 10일
0
post-thumbnail

기본 매커니즘

두 단계로 진행된다.

  1. Build 단계 : 작은 쪽 테이블을 읽어 해시 테이블을 생성한다.
  2. Probe 단계 : 큰 쪽 테이블을 읽어 해시 테이블을 탐색하며 조인한다.

해시 조인이 빠른 이유

  • Hash Area에 생성한 테이블을 이용, 조인 프로세싱은 NL조인과 같음.
  • 소트 머지 조인처럼 해시 테이블을 PGA 영역에 할당함
  • 해시 조인은 NL 조인처럼 조인 과정에서 발생하는 랜덤 액세스 부하가 없고, 소트 머지 조인처럼 양쪽 집합을 미리 정렬하는 부하도 없다.
  • 해시 테이블을 생성하는 비용이 수반되지만, 둘 중 작은 집합을 Build Input으로 선택하므로 대개는 부담이 크지 않다.
  • Build Input이 PGA 메모리에 담길 때, 인메모리(In-Memory) 해시 조인일 때 가장 효과적인 이유가 바로 여기에 있다.

대용량 Build Input 처리

두 테이블이 모두 대용량 테이블이라 인메모리 해시조인이 불가능하다면?

이럴때 2단계로 나눠 분할-정복 (Divide & Conquer) 방식을 사용한다.

파티션 단계

조인하는 양쪽 집합의 조인 컬럼에 해시함수를 적용하고, 반환된 해시 값에 따라 동적으로 파티셔닝 한다.

독립적으로 처리할 수 있는 여러개의 작은 서브 집합으로 분할함으로서 파티션짝을 생성하는 단계

조인 단계

  • 파티션 단계 완료시 파티션짝에 대해 하나씩 조인 수행.
  • 각각 Build Input과 Probe Input 은 독립적으로 결정된다.
  • 즉, 파티션하기 전 어느쪽이 작은 테이블이었는지에 상관없이 각 파티션 짝별로 작은 쪽을 Build Input으로 선택! 해시 테이블 생성!
  • 해시테이블 생성후 반대쪽 파티션 로우를 하나씩 읽으며 해시테이블 탐색. 모든 파티션 짝에 대한 처리를 마칠때까지 반복.

해시 조인 실행계획 제어

해시 조인 실행계획을 제어할 때 아래와 같이 use_hash 힌트를 사용한다.

SELECT /*+ use_hash(e c) */
       e.사원번호, e.사원명, e.입사일자
     , c.고객번호, c.고객명, c.전화번호, c.최종주문금액
  FROM 사원 e, 고객 c
 WHERE c.관리사원번호 = e.사원번호
   AND e.입사일자 >=19960101AND e.부서코드 = ‘Z123’
   AND c.최종주문금액 >= 2000
  • use_hash 힌트만 사용하면 Build Input을 옵티마이저가 선택, 일반적으로 둘 중 카디널리티가 작은 테이블을 선택.
  • Build Input을 사용자가 직접 선택하려면 leading이나 ordered 힌트를 사용하면 됨.
  • 이들 힌트로 지시한 순서에 따라 먼저 읽는 테이블을 Build Input으로 선택한다.
SELECT /*+ leading(e) use_hash(c) */ -- 또는 ordred use_hash(c)
       e.사원번호, e.사원명, e.입사일자
     , c.고객번호, c.고객명, c.전화번호, c.최종주문금액
  FROM 사원 e, 고객 c
 WHERE c.관리사원번호 = e.사원번호
   AND e.입사일자 >=19960101AND e.부서코드 = ‘Z123’
   AND c.최종주문금액 >= 2000

아래와 같이 swap_join_inputs 힌트로 Build Input을 직접 선택하는 방법도 있다.

SELECT /*+ use_hash(e c) swap_join_inputs(e) */
       e.사원번호, e.사원명, e.입사일자
     , c.고객번호, c.고객명, c.전화번호, c.최종주문금액
  FROM 사원 e, 고객 c
 WHERE c.관리사원번호 = e.사원번호
   AND e.입사일자 >=19960101AND e.부서코드 = ‘Z123’
   AND c.최종주문금액 >= 2000

조인 메소드 선택 기준

해시조인이 빨라도 단점이 있다. 수행빈도가 높은 쿼리에 대해 위험하다.

  • 소량 데이터 조인 ⇒ NL 조인
  • 대량 데이터 조인 ⇒ 해시 조인
  • 대량 데이터 조인인데, 해시조인으로 처리불가시 (조인 조건식이 =이 아닐때) ⇒ 소트머지 조인

수행빈도가 매우 높은 쿼리에 대한 기준

  1. NL 조인과 해시 조인이 성능이 같으면 ⇒ NL 조인
  2. 해시 조인이 약간 빨라도 ⇒ NL 조인
  3. NL조인보다 해시 조인이 매우 빠른 경우 ⇒ 해시 조인

왜 2번처럼 해시 조인이 NL 보다 빨라도 NL 조인을 써야 하는가?

  • NL조인에 사용되는 인덱스는 영구적으로 유지하면서 다양한 쿼리를 위해 공유 및 재사용하는 자료구조이다.
  • 해시 테이블은 단 하나의 쿼리를 위해 생성하고 사용이 끝나면 소멸하는 자료구조이다.
  • 해시 조인을 사용하면 CPU와 메모리 사용률을 크게 증가시킨다.
  • 해시 맵을 만드는 과정에서 여러 래치 경합도 발생!

해시 조인이 사용되는 3가지 조건

  • 수행 빈도가 낮고
  • 쿼리 수행 시간이 오래 걸리는
  • 대량의 데이터를 조인할 때.
profile
뭉실뭉실 코더 운구름

0개의 댓글