MySQL 8.0.18
버전 부터 추가된 기능이며 PostgreSQL, Oracle.. 많은 RDBMS에서는 이전부터 이미 지원하는 기능입니다.
☠️ 하지만 진짜 Hash join이 NLJ보다 무조건 빠르지는 않다.
예상대로 NLJ이 hash join보다 필요한 모든 레코드를 늦게 발견합니다.
실질적인 필요 레코드의 탐색이 쿼리의 끝은 아님. 탐색 범위를 줄일 수 없는 체크조건이 포함될 수도 있습니다.
중요한 것은 마지막 레코드 발견 영역은 Hash Join이 앞에 있으나
첫 레코드 발견 영역은 NLJ가 앞에 있습니다.
Hash Join
: Best Througput 전략에 적합
Nested Loop Join
: Best Response-time 전략에 적합
-> MySQL 서버는 주로 조인 조건의 컬럼이 인덱스가 없거나
조인 대상 테이블중 일부의 레코드 건수가 매우 적은 경우
등에 대해서만 Hash Join 알고리즘을 사용
-> Hash Join은 Nested Loop Join이 사용되기에 적합하지 않은 경우를 위한 차선책
SELECT *
FROM employees e IGNORE INDEX(PRIMARY, ix_hiredate)
INNER JOIN dept_emp de IGNORE INDEX(ix_empno_fromdate, ix_fromdate)
ON de.emp_no=e.emp_no AND de.from_date=e.hire_date;
일반적으로 hash join은 Build-phase
, Probe-phase
단계로 처리됩니다.
Build-phase
: 조인 대상 테이블 중에서 레코드 건수가 적어 해시 테이블로 만들기에 용이한 테이블을 골라서 메모리에 해시 테이블을 생성
Probe-phase
: 나머지 테이블의 레코드를 읽어서 해시 테이블의 일치 레코드를 찾는 과정
EXPLAIN FORMAT=TREE를 통해 build, probe table을 확인할 수 있습니다.
Hash table을 메모리에 저장할 때 Join Buffer를 사용합니다.
이러한 경우 build, probe table을 적당한 크기의 청크로 분리한 다음
해시조인을 처리
Join result
와 probe table의 chunk
가 함께 생성
Disk의 build chunk를 hash table에 올리고
probe table의 chunck를 읽어 다시 조인후 결과 생성
이렇게 디스크에 저장된 청크 개수만큼 반복 처리하여 조인 결과를 완성시킵니다.