Hash Join 이란
조인을 수행할 테이블의 조인 컬럼을 기준으로 해쉬함수를 수행한 후, 서로 동일한 해쉬 값을 갖는 것 중에서 실제 값이 같은지 비교하면서 조인을 수행하는 메커니즘이다.
- 선행 테이블에서 주어진 조건을 만족하는 로우 검색
- 선행 테이블의 조인 키를 기준으로 해쉬 함수 적용 후, 해쉬 테이블 생성. 조인 컬럼과 검색하는 컬럼도 함께 저장
- 선행 테이블의 조건을 만족하는 모든 로우를 1~2 과정 수행 후, 후행 테이블에서 주어진 조건을 만족하는 로우 검색
- 후행 테이블의 조인 키를 기준으로 해쉬 함수를 적용하여 선행 테이블과 비교
- 조인 성공 시, 추출버퍼에 격납
- 후행 테이블의 조건을 만족하는 모든 로우를 3~5 과정 수행
사이즈가 작은 테이블을 선행으로 사용하는 것이 좋다.
Hash Join 채용 조건
해쉬 조인은 등가조건의 조인이고, 조인하는 컬럼에 Index가 없는 경우에 사용된다
해쉬 조인의 사용유무는 EXPLAIN ANALYZE 또는 EXPLAIN FORMAT=TREE: 로 확인 가능하다.
# MySQL 8.0.20 에서 Hash Join이 강화되어 채용 조건이 확대되었다
- 등가 조인 이외의 INNER JOIN
- 세미조인
- 안티조인
- LEFT OUTER JOIN / RIGHT OUTER JOIN
https://dev.mysql.com/doc/refman/8.0/en/hash-joins.html
Hash Join 검증
t1, t2 테이블 작성 후 테스트용 데이터(랜덤으로 생성한 20문자) 16384건 등록하자.
mysql> CREATE TABLE t1 (a VARCHAR(20)); Query OK, 0 rows affected (0.10 sec) mysql> CREATE TABLE t2 (a VARCHAR(20)); Query OK, 0 rows affected (0.02 sec) mysql> INSERT INTO t1 VALUES (); mysql> INSERT INTO t1 SELECT * FROM t1; mysql> INSERT INTO t1 SELECT * FROM t1; mysql> INSERT INTO t1 SELECT * FROM t1; ~(생략)~ mysql> INSERT INTO t1 SELECT * FROM t1; mysql> INSERT INTO t1 SELECT * FROM t1; mysql> INSERT INTO t1 SELECT * FROM t1; Query OK, 8192 rows affected (0.11 sec) Records: 8192 Duplicates: 0 Warnings: 0 mysql> UPDATE t1 SET a = SUBSTRING(MD5(RAND()), 1, 20); Query OK, 16384 rows affected (0.81 sec) Rows matched: 16384 Changed: 16384 Warnings: 0 mysql> INSERT INTO t2 SELECT * FROM t1; Query OK, 16384 rows affected (0.58 sec) Records: 16384 Duplicates: 0 Warnings: 0 mysql> UPDATE t2 SET a = SUBSTRING(MD5(RAND()), 1, 20); Query OK, 16384 rows affected (0.30 sec) Rows matched: 16384 Changed: 16384 Warnings: 0
작성한 테이블 t1, t2에 대하여 아래의 쿼리를 실행해보자
mysql> EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a; +-------------------------------------------------------------------------------------------------------------------+ | EXPLAIN | +-------------------------------------------------------------------------------------------------------------------+ | -> Inner hash join (t1.a = t2.a) (cost=26368857.25 rows=26367169) (actual time=42.485..52.619 rows=5 loops=1) -> Table scan on t1 (cost=0.01 rows=16269) (actual time=0.016..10.830 rows=16384 loops=1) -> Hash -> Table scan on t2 (cost=1644.95 rows=16207) (actual time=0.051..10.163 rows=16384 loops=1) | +-------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.05 sec)
실행계획에 "Inner hash join" 이 출력되어 있고, Hash Join이 실행된 것을 알 수 있다.
# Refer
https://mysqlserverteam.com/hash-join-in-mysql-8/