본문 바로가기

오라클 성능고도화 2권

Chap02. 03 해시 조인

01. 기본 메커니즘


  • NL 조인과 Sort Merge Join이 효과적이지 못한 상황에 대한 대안으로서 개발
  • 둘 중 작은 Table(Build Input)을 읽어 Hash Area에 Hash Table을 생성하고, 반대쪽 큰 Table(Probe Input)을 읽어 Hash Table을 탐색하면서 Join 하는 방식
  • Hash Join이 NL보다 빠른 이유
    • Hash Table이 PGA 영역에 할당된다는 데 있기 때문, NL 조인은 Outer 테이블에서 읽히는 레코드마다 Inner 쪽 테이블 버퍼 캐시 탐색을 위해 래치 획득을 반복하지만, Hash Join은 래치 획득 없이 PGA에서 빠르게 데이터를 탐색합니다.
  • Hash Join이 가능한 Join 조건은 무조건 등치('=') 조건 일때

Hash Join

 

 

02. 힌트를 이용한 조인 순서 및 Build Input 조정


SELECT /*+ USE_HASH(D E) */ 
       D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME
  FROM DEPT D, EMP E
 WHERE D.DEPTNO = E.DEPTNO;

 

  • USE_HASH : 두 Table을 Hash Join으로 풀어라
  • USE_HASH만 주었기에 Build Input은 옵티마이저의 판단에 의해 결정
  • Hash Join 관련된 중요 Hint
    • SWAP_JOIN_INPUTS : Hash Join 시 사용자가 Build Input 지정
    • NO_SWAP_JOIN_INPUTS : Hash Join 시 사용자가 Probe Input 지정

Hash Join 실행계획

.

 

 

SELECT /*+ use_hash(d e) swap_join_inputs(e) */ d.deptno, d.dname, e.empno ....

SELECT /*+ leading(e) use_hash(d) */ d.deptno, d.dname, e.empno, e.ename ....

----------------------------------------------------------------------------------
ID  |  Operation               |  Name |  Rows  | Bytes  | Cost (%CPU)  |  Time
----------------------------------------------------------------------------------
0   |  SELECT STATEMENT        |       |    14  |   364  |    7 (15)    | 00:00:01 
1   |    HASH JOIN             |       |    14  |   364  |    7 (15)    | 00:00:01 
2   |      TABLE ACCESS FULL   |  EMP  |    14  |   182  |    3  (0)    | 00:00:01 
3   |      TABLE ACCESS FULL   |  DEPT |     4  |    52  |    3  (0)    | 00:00:01

 

 

03. 두 가지 해시 조인 알고리즘


 

  • 오라클은 해시 조인을 위해 두 가지 알고리즘을 사용

첫번째

-- FULL Hint를 넣은 이유는 기존에 사용하던 Index 때문에 
SELECT /*+ LEADING(R, C, L, D, E) FULL(D) FULL(E) USE_HASH(C) USE_HASH(L) USE_HASH(D) USE_HASH(E) */
       E.FIRST_NAME, E.LAST_NAME, D.DEPARTMENT_NAME
     , L.STREET_ADDRESS, L.CITY, C.COUNTRY_NAME, R.REGION_NAME
  FROM HR.REGIONS R, HR.COUNTRIES C, HR.LOCATIONS L, HR.DEPARTMENTS D, HR.EMPLOYEES E
 WHERE D.DEPARTMENT_ID = E.DEPARTMENT_ID
   AND L.LOCATION_ID = D.LOCATION_ID
   AND C.COUNTRY_ID = L.COUNTRY_ID
   AND R.REGION_ID = C.REGION_ID;

 

 

  • Leading Hint의 의도로 REGIONS -> COUNTRIES -> LOCATIONS -> DEPARTMENTS -> EMPLOYEES 순으로 각각 Hash Join으로 처리하라고 지시하고 있습니다.
  1. REGIONS Table을 Build Input으로 Hash Area에 담고, Country Index를 읽어 Hash Table을 탐색하면서 Join 수행
  2. 위결과를 Build Input으로 Hash Area 담고, Location Table을 읽어 Hash Table을 탐색하면서 Join 수행
  3. ....
  4. ...

 

 

두번째

  • 첫번째 Build Input에 대한 지정을 제외한 나머지에 Build Input은 사용자가 직접 지정하는 방법
SELECT /*+ LEADING(R, C, L, D, E) FULL(D) FULL(E) USE_HASH(C) USE_HASH(L) USE_HASH(D) USE_HASH(E)
           SWAP_JOIN_INPUTS(L)
           SWAP_JOIN_INPUTS(D)
           SWAP_JOIN_INPUTS(E) */
       E.FIRST_NAME, E.LAST_NAME, D.DEPARTMENT_NAME
     , L.STREET_ADDRESS, L.CITY, C.COUNTRY_NAME, R.REGION_NAME
  FROM HR.REGIONS R, HR.COUNTRIES C, HR.LOCATIONS L, HR.DEPARTMENTS D, HR.EMPLOYEES E
 WHERE D.DEPARTMENT_ID = E.DEPARTMENT_ID
   AND L.LOCATION_ID = D.LOCATION_ID
   AND C.COUNTRY_ID = L.COUNTRY_ID
   AND R.REGION_ID = C.REGION_ID;

SWAP_JOIN_INPUTS로 사용자지정 Build Input

 

  1. Hash Table 생성 : EMPLOYTEES, DEPARTMENTS, LOCATIONS, REGIONS 4개의 Table에 대한 Hash Table을 먼저 생성
  2. id 7번 Hash Join : COUNTRIES에서 한건을 읽어 REGIONS Hash Table을 탐색
  3. id 5번 Hash Join : 2번에서 Join 성공한 Record는 LOCATIONS Hash Table을 탐색
  4. id 3번 Hash Join : 3번에서 Join 성공한 Record는 DEPARTMENTS Hash Table을 탐색
  5. id 1번 Hash Join : 4번에서 Join 성공한 Record는 EMPLOYEES Hash Table을 탐색
  6. 2~5번 과정을 COUNTRIES INDEX를 모두 SCAN할 때까지 반복

 

 

가장 큰 Table인 EMPLOYEES를 Probe Input 으로 두어 한건씩 읽을 때

  • EMPLOYEES(PROBE TABLE)로 생성하고, 그 외 테이블을 HASH TABLE로 읽도록하여 JOIN을 수행해 가면,
    • 작은 테이블로 빠르게 해시 테이블을 생성하고 나서, 큰 테이블에서 일부 레코드만 스캔하다가 조인을 멈출 수 있는데, 이는 NL 조인의 가장 큰 장점인 부분범위처리를 해시 조인에서도 갖게 되는 것입니다.

 

04. Build Input이 Hash Area를 초과할 때 처리 방식


  • In-Memory 해시 조인이 불가능할 때 오라클은 어떤 방식으로 해시 조인을 처리할까??
  1. Grace 해시 조인
    • 단계
      • ① 파티션 단계
      • ② 조인 단계
  2. Hybrid 해시 조인
  3. Recursive 해시 조인(=Nested-loops 해시 조인)
  4. 비트-벡터 필터링

 

 

 

05. Build Input 해시 키 값에 중복이 많을 때 발생하는 비효율


  • 해시 알고리즘의 성능은 해시 충돌(collision)을 얼마나 최소화 할 수 있느냐에 달렸습니다.
    • 이를 방지하려면 그만큼 많은 해시 버킷을 할당해야만 합니다.
    • 오라클은 충분히 많은 개수의 버킷을 할당함으로써 버킷 하나당 하나의 키 값만 갖게 하려고 노력합니다.
    • 해시 버킷이 아무리 많이 할당하더라도 해시 테이블에 저장할 키 컬럼에 중복 값이 많으면 하나의 버킷에 많은 엔트리가 달릴 수 밖에 없으며, 해시 버킷을 빨리 찾다는다 하더라도 중복된 키 값을 스캔하는 단계에서 많은 시간을 허비하게 되어 탐색 속도가 현저히 저하됩니다.

 

예시 쿼리

주문 Table과 주문체결 Table 기억

주문체결 Table을 두번 읽어 하나는 매도주문접수번호, 하나는 매수주문접수번호로 UNION ALL 한 후 찾기

 

 

06. 해시 조인 사용기준

 


'오라클 성능고도화 2권' 카테고리의 다른 글

Chap02. 05 Outer 조인  (0) 2021.08.08
Chap02. 04 조인 순서의 중요성  (0) 2021.08.08
Chap02. 02 소트 머지 조인  (0) 2021.08.08
Chap02. 01 Nested Loops 조인  (0) 2021.08.06
Chap02 조인 원리와 활용  (0) 2021.08.05