해시 조인 튜닝 실습
해시 조인 튜닝
개발자를 위한 오라클 SQL 튜닝 내용에서 참고한 내용입니다.
Intro
상품과 주문에 대한 모델링
상품 정보 10만건 생성, 주문정보 500만건 생성
하나의 제품은 0개 또는 1개 이상의 주문을 가질 수 있다.
하나의 주문은 반드시 한 개의 제품을 갖는다.
Outer 테이블(주문 정보)과 Inner 테이블(상품 정보)을 설정하여 중첩 루프 조인으로 쿼리 실행 확인
대용량 테이블인 주문 정보 테이블이 Outer 테이블로 지정되어 매우 큰 성능 부하 확인
튜닝 후 상품 테이블을 Build Input로 지정, FULL 힌트를 통해 Build Input을 테이블 풀 스캔으로 유도
USE_HASH 힌트로 주문정보 테이블을 Probe Input으로 지정하여 해시 조인을 수행
데이터 준비
상품, 주문 정보 테이블 생성
CREATE TABLE TB_PRDT
(
PRDT_CD VARCHAR2(6), -- 상품코드
PRDT_NM VARCHAR2(50), -- 상품명
REL_DT VARCHAR2(8), -- 출시일자
COST_AMT NUMBER(15), -- 원가금액
INST_DTM DATE, -- 입력시간
INST_ID VARCHAR2(50), -- 입력자ID
UPDT_DTM DATE, -- 수정시간
UPDT_ID VARCHAR2(5) -- 수정자ID
);
CREATE TABLE TB_ORD
(
ORD_NO VARCHAR2(10), -- 주문번호
ORD_DT VARCHAR2(8), -- 주문일자
ORD_NM VARCHAR2(150), -- 주문이름
ORD_AMT NUMBER(15), -- 주문금액
PRDT_CD VARCHAR2(6), -- 상품코드
SALE_GB VARCHAR2(2), -- 판매구분
PAY_GB VARCHAR2(2), -- 결제구분
CUST_ID VARCHAR2(10), -- 고객ID
INST_DTM DATE, -- 입력시간
INST_ID VARCHAR2(50), -- 입력자ID
UPDT_DTM DATE, -- 수정시간
UPDT_ID VARCHAR2(5) -- 수정자ID
);상품 정보 더미 데이터 생성
상품 정보에 연관된 주문 정보 더미 데이터 생성
제약 조건 생성
통계 정보 생성
해시 조인으로 성능 극대화
SQL 분석
LEADING 힌트를 이용하여 주문 정보 테이블을 Outer 테이블로 지정
Outer 테이블을 스캔 시 TB_ORD_IDX01 인덱스를 이용
USE_NL 힌트를 이용하여 상품정보 테이블을 Inner 테이블로 지정하여 중첩 루프 조인을 수행하도록 유도한다.
SQL의 문제점
대용량 테이블인 주문정보 테이블이 outer 테이블로 지정되어 매우 큰 성능 부하가 예상된다.
주문일자 컬럼 조건만으로는 대량의 행이 나오기 때문에 그에 따른 테이블 랜덤 액세스 부하가 발생한다.
Execute Plan
TB_ORD_IDX01을 인덱스 범위 스캔(INDEX RANGE SCAN)한다.
TB_ORD_IDX01의 ROWID를 이용하여 TB_ORD 테이블을 테이블 랜덤 액세스(TABLE ACCESS BY INDEX ROWID)한다.
TB_ORD 테이블의 PRDT_CD 컬럼 값을 이용하여 TB_PRDT_PK 인덱스를 인덱스 유일 스캔(INDEX UNIQUE SCAN)한다.
3번과 5번의 연산을 중첩 루프 조인(NESTED LOOPS)를 수행한다.
TB_PRDT_PK 에서 나온 ROWID를 이용하여 TB_PRDT 테이블을 테이블 랜덤 액세스(TABLE ACCESS BY INDEX ROWID)한다.
중첩 루프 조인과 TB_PRDT 테이블을 테이블 랜덤 액세스(TABLE ACCESS BY INDEX ROWID)한다.
SELECT 절의 연산을 수행한다.

SQL 분석
LEADING 힌트를 이용하여 작은 집합인 상품 테이블을 Build Input으로 지정
FULL 힌트를 이용하여 Build Input을 테이블 풀 스캔으로 유도
USE_HASH 힌트를 이용하여 주문 테이블을 Probe Input으로 지정하고 해시 조인을 수행
Execute Plan
TB_PRDT 테이블을 테이블 풀 스캔(TABLE ACCESS FULL)을 수행
TB_ORD 테이블을 테이블 풀 스캔(TABLE ACCESS FULL)을 수행
TB_PRDT 테이블을 Build Input, TB_ORD 테이블을 Probe Input으로 하여 해시 조인(Hash Join)을 수행
TB_PRDT 테이블을 Build Input, TB_ORD 테이블을 Probe Input으로 하여 해시 조인(Hash Join)을 수행

인라인 뷰를 이용한 해시 조인으로 성능 극대화
상품 정보 생성하기
더미 테이블 생성하기
주문정보 테이블 생성하기
제약 조건 생성하기
인덱스 생성 및 통계 정보 생성하기
튜닝 전 쿼리
SQL 분석
TB_PRDT_SALE_DAY 테이블과 TB_PRDT 테이블을 조인
조인 방식은 옵티마이저의 선택에 따른다.
SQL의 문제점
TB_PRDT 테이블과 TB_PRDT_SALE_DAY 테이블은 1:M 관계
1쪽 집합인 TB_PRDT 테이블의 PRDT_CD를 기준으로 GROUP BY하여 집계 결과를 계산한다.
SQL은 인라인 뷰를 이용하여 M 쪽의 집합인 TB_PRDT_SALE_DAY 테이블을 먼저 GROUP BY한 후 TB_PRDT 테이블과 1:1 관계를 만든 다음 다음 조인 연산을 수행한다면 최적의 성능을 낼 수 있다.
Execute Plan
TB_PRDT_SALE_DAY 테이블을 풀 스캔(TABLE ACCESS FULL)한다.
TB_PRDT 테이블을 풀 스캔(TABLE ACCESS FULL) 한다.
4번과 5번을 해시 조인(HASH JOIN)한다.
GROUP BY 연산을 수행한다.
SELECT 절을 연산 수행한다.

튜닝
SQL 분석
NO_MERGE 힌트를 사용하여 인라인 뷰 A가 메인 쿼리와 같은 레벨로 View Merging되지 않도록 한다.
TB_PRDT_SALE_DAY 테이블을 인라인 뷰 내에서 읽는다.
PRDT_CD를 기준으로 GROUP BY하여 TB_PRDT 테이블과 조인 연산을 최소화한다.
Execute Plan
TB_PRDT_SALE_DAY 테이블을 풀 스캔(TABLE ACCESS FULL) 한다.
GROUP BY 연산을 수행
4번과 3번의 연산을 인라인 뷰(View)로 구성
TB_PRDT 테이블을 테이블 풀 스캔(TABLE ACCESS FULL)한다.
2번과 5번을 해시 조인(HASH JOIN)한다.
SELECT 절의 연산을 수행한다.

Last updated
Was this helpful?