■ hash join
1. 정의
- 대량의 데이터에 대한 조인 연산에서 효과적으로 사용되는 조인 알고리즘 중 하나.
- Nested loop join의 랜덤 액세스 부다과 Sort Merge Join의 정렬 작업 부담을 피하기 위해서 사용됨.
2. 동작원리
- 작은 쪽의 집합을 Build Table로 선택하여 Hash Table 을 생성.
- 큰 쪽의 집합을 Probe 하여 Hash Table 을 탐색하여 조인 수행.
- Hash Table은 Hash Area Size로 지정된 메모리 영역에 생성.
3. 조인 제약 조건
- Equal(=) 조건만 가능: Hash Join은 등호 조건에서만 사용 가능하며, 일반적으로 등호 조건에서 성능이 가장 좋음.
4. 효과적인 경우
- 작은 집합이 Build Table로 생성될 때.
- Hash Key에 중복 값이 거의 없는 경우.
- Hash Key 충돌이 발생하지 않는 경우
5. 설정 매개변수
- `hash_area_size`: Hash Table이 생성되는 메모리 공간 크기를 지정.
6. 장단점
1) 장점
- 대량의 데이터에 효과적.
- Random 액세스나 정렬 작업 부담이 적음
2) 단점
- Equal(=) 조건에만 사용 가능.
- 작은 집합의 크기와 Hash Key의 품질에 민감.
<hr sess>
select /*+ gather_plan_statistics leading(d,e) use_hash(e) */
d.depatment_id, d.department_name, e.employee_id, e.last_name, e.salary
from departments d, employees e
where d.department_id = e.department_id;
#) 실행 계획 확인
select * from table(dbms_xplan.display_cursot(null, null, 'allstats last'));
☆ hash_area_size : PGA (Program Global Area) 내에 위치한 메모리 영역으로, Hash Join에서 사용되는 Hash Table이 생성되는 공간 크기이다.
▷ probe: sql문을 scan 한다.
- Probe는 Hash Join에서 큰 쪽의 테이블을 스캔하고 Hash Table을 탐색하는 단계
- 큰 테이블의 각 행은 Hash Key를 기반으로 해시 함수를 적용하고, 해당 해시 버킷을 찾아가며 Hash Table을 탐색한다.
- 조인 조건을 확인하면서 일치하는 행을 찾아내는 과정이다.
▷빌드테이블과 프로브 테이블
- Hash Join에서 작은 테이블을 Build Table로 지정하고 큰 테이블을 Probe Table로 지정한다.
- Build Table은 작은 테이블로, Hash Table을 생성하여 해시 버킷에 행을 저장한다.
- Probe Table은 큰 테이블로, Hash Key를 계산하여 해당 버킷을 찾아가며 Hash Table을 탐색한다.
※ 요약 ※
- `hash_area_size`는 PGA 내의 Hash Join에 사용되는 Hash Table의 메모리 크기를 지정하는 매개변수이다.
- Hash Join은 Build Table과 Probe Table로 나누어지며, 작은 테이블을 Build Table로 선택하는 것이 성능 향상에 도움이 된다.
- 빌드 테이블의 중요성은 Hash Table의 생성 및 해시 조인 성능에 큰 영향을 미친다.
#1) 기본 use_hash() 사용
<hr sess>
select /*+ gather_plan_statistics leading(d,e) use_hash(e) */
d.department_id, d.department_name, e.employee_id, e.last_name, e.salary
from departments d, employees e
where d.department_id >= e.department_id;
#) 실행 계획 확인
select * from table(dbms_xplan.display_cursot(null, null, 'allstats last'));
#2) 빌드 테이블 바꿔보기
<hr sess>
select /*+ gather_plan_statistics leading(e,d) use_hash(e) */
d.department_id, d.department_name, e.employee_id, e.last_name, e.salary
from departments d, employees e
where d.department_id = e.department_id;
#) 실행 계획 확인
select * from table(dbms_xplan.display_cursor(null, null, 'allstats last'));
→ 큰 값으로 빌드 테이블을 만들면 i/o 발생이 잦아서 성능이 안좋다. 그렇다고 값이 작게 나와도 좋지 않다.
(데이터 양이 적어서 값이 작게 나옴)
#3) 3개의 테이블로 join
select /*+ gather_plan_statistics leading(l,d,e) use_hash(d) use_hash(e) */
d.department_id, d.department_name, e.employee_id, e.last_name, e.salary, l.city, l.street_address
from departments d, employees e, locations l
where d.department_id = e.department_id
and d.location_id = l.location_id;
#) 실행 계획 확인
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
#) use_hash() 사용
select /*+ gather_plan_statistics leading(d,e,l) use_hash(e) use_hash(l) */
d.department_id, d.department_name, e.employee_id, e.last_name, e.salary, l.city, l.street_address
from departments d, employees e, locations l
where d.department_id = e.department_id
and d.location_id = l.location_id;
#) 실행 계획 확인
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
'Data Base > SQL 튜닝' 카테고리의 다른 글
Query Transformation, 서브쿼리 처리 방식(in, exists) (0) | 2024.02.23 |
---|---|
pushing subquery, view merging, join 조건 pushdown (0) | 2024.02.23 |
Sort Merge Join (0) | 2024.02.20 |
join 실행 계획 (0) | 2024.02.19 |
join 문, index 설정 (0) | 2024.02.19 |