위와 같이 테이블과 인덱스 설정이 있다고 가정해보자.
모든 이미지 출처는 https://www.youtube.com/watch?v=13Yga-pv-ls&t=190s 이다. 전광철님 감사합니다.
Nested Loop Join
하나의 테이블을 기준으로 각 row를 추출하고, 그때마다 순차적으로 상대 테이블에서 연관된 row들을 JOIN에 의해 추출하는 방식.
3번과 4번 작업을 보면 모두 Dept 테이블에서 이루어지고 있다. 첫번째로 풀스캔을 뜨면서 인덱스에 해당하는 값들을 Index Dept_index로 추출하고, 3번과 4번의 결과를 2번의 Nested Loop 작업으로 Join 연산을 하고 있다. 그 이후에 EMP테이블과 Join을 하는 과정을 1번 작업에서 해주고 있는 것이다.
따라서 튜닝을 할 때는 다음과 같은 포인트를 체크해야 한다.
- 조인 횟수의 최소화를 위한 조인 순서의 최적화
- 조인 조건에 대한 인덱스 구성 및 사용
Nested Loop를 사용할 때는 인덱스에 의한 랜덤 액세스를 하기 때문에 대용량 처리시에는 사용하지 말아야 한다.
그리고 데이터를 먼저 읽어들일 테이블, Driving table은 로우 수가 적을수록 유리하기 때문에
where 절의 조건으로 적절하게 row를 제한해야 하며, Join시 사용할 칼럼에는 적절한 인덱스가 있어야 한다.
SortMerge 조인
SM 조인 방식은 각 테이블로부터 동시에 데이터를 읽어들인 후, 연결고리 칼럼을 대상으로 정렬 작업을 수행한다. 정렬이 모두 끝나면 조인을 한다.
먼저 EMP 테이블에 대해서 DEPT_INDEX를 활용해서 EMP 테이블을 전체 읽는 작업을 수행했다. 이 과정에서는 인덱스로 데이터를 접근했기 때문에 이미 Sorting이 되어있다.
그리고 DEPT에 대한 데이터 접근도 동시에 이루어지는데 얘는 Sorting이 안되어 있어서 부서 번호로 SORT JOIN을 해주었다.
이 결과에 대해서 Merge 해주고 작업이 마무리가 된다.
튜닝포인트는 다음과 같다.
- 병렬적으로 진행되는 데이터 read 작업이 테이블별로 빨리 수행되어야 한다.
- 정렬 작업을 위한 메모리가 최적화(SORT_AREA_SIZE)되어야 한다.
소트 머지의 특징은 연결고리 컬럼에 인덱스가 전혀 없어도 빠른 조인을 수행할 수 있기 때문에 where 절의 조건으로 조인 범위를 줄이기 못하는 경우에 효율적이다. 조인이 되는 두 집합은 모두 정렬되어야 한다.
Hash Join
NL 조인과 SM 조인은 각각 인덱스로 랜덤 액세스로 인한 오버헤드 발생, 정렬 작업으로 인한 오버헤드 발생의 문제가 존재한다.
이를 해결하기 위해 Hash Join 을 사용하는 방식이 있다.
해시 조인의 수행 절차는 다음과 같다.
- Driving 테이블에서 데이터를 read 후 해시값 생성
- Driving 테이블의 해시값을 메모리에 적재
- 조인 대상 테이블에서 데이터를 read 후 해시값 생성
- 조인 대상 테이블의 해시값을 메모리에 적재
- 각각의 해시값으로 조인 수행
2번과 3번에서 각각의 테이블을 풀스캔한 후 해시값에 대해서 조인하였다.
해시 조인의 튜닝 포인트는 다음과 같다.
- 드라이빙 테이블이 중요하다 (주로 사이즈가 작은 테이블)
- 각 테이블로부터 데이터를 빨리 처리하도록 한다.
- 조인 작업을 위한 메모리(Hash_area_size)를 최적화해야한다.
하지만 Hash 조인이 효율적이기 위해서는 하드웨어 자원이 넉넉해야 한다. Hash join을 사용하기 위해서는 Hash bucket이 구성되는데 이를 위해서는 많은 메모리와 CPU를 필요로 하기 때문이다. 또한 모든 조인에서 사용할 수 있는 NL, SM과는 다르게 해시 조인은 Equi 조인에서만 사용이 가능하다.
정리하자면 nl 조인은 인덱스 구성, sm은 정렬, hash 는 메모리 확보가 튜닝의 중요한 요소가 되겠다.
'Study > Oracle' 카테고리의 다른 글
쿼리 성능 측정시 체크 리스트 정리 (0) | 2022.03.19 |
---|---|
조인의 개념과 실행 절차 (0) | 2022.03.19 |
Oracle의 B-Tree Index (0) | 2022.03.18 |