SELECT E.사원명, C. 고객명, C.전화번호
FROM 사원 E, 고객 C
WHERE E.입사일자 >= '19960101'
AND C.관리사원번호 = E.사원번호;
1) 사원_X1 인덱스에서 입사일자 ≥’19960101’ 인 첫 번째 레코드를 찾는다.
2) 인덱스에서 읽은 ROWID로 사원 테이블 레코드를 찾아간다.
3) 사원 테이블에서 읽은 사원번호 ‘0006’으로 고객_X1 인덱스를 탐색한다.
4) 고객_X1 인덱스에서 읽은 ROWID로 고객 테이블 레코드를 찾아간다.
사원_X1 인덱스에서 입사일자 조건인 모든 레코드에 대해 같은 과정을 반복한다.
/*+ ordered us_nl(c) */
ordered
: FROM 절에 기술한 순서대로 조인us_nl
: NL 방식으로 조인select /*+ ordered use_nl(B) use_nl(C) use_hash(D) */ *
from A, B, C, D
where ...
A→B→C→D 순으로 조인하되, B, C와 조인할 때는 NL 방식 조인, D와 조인할 때는 해시 방식으로 조인select /*+ leading(C, A, D, B) use_nl(A) use_nl(D) use_hash(B) */ *
from A, B, C, D
where ...
leading()
: FROM 절을 수정하지 않아도 제어할 수 있다는 장점select /*+ ordered use_nl(c) index(e) index(c)*/
e.사원번호, e.사원명, e.입사일자,
c.고객번호, c.고객명, c.전화번호, c.최종주문번호
from 사원 e, 고객 c
where c.관리사원번호 = e.사원번호 -- 1️⃣
and e.입사일자 >= '19960101' -- 2️⃣
and e.부서코드 = 'Z123' -- 3️⃣
and c.최종주문금액 >= 20000 -- 4️⃣
사원_PK : 사원번호
사원_X1 : 입사일자
고객_PK : 고객번호
고객_X1 : 관리사원번호
고객_X2 : 최종주문금액
사원_X1
index range scan사원_X1
에서 읽은 ROWID로 사원 테이블에 엑세스하여 부서코드에 조건이 만족하는지 확인고객_X1
index range scan고객_X1
에서 읽은 ROWID로 고객 테이블에 엑세스하여 최종주문금액 조건을 만족하는지 확인사원_X1
인덱스를 읽고 사원 테이블에 엑세스 하는 부분💡 NL 조인은 소량 데이터를 주로 처리하거나 부분범위 처리가 가능한 온라인 트랜잭션 처리 시스템(OLTP)에 적합한 조인 방식이다.
select /*+ ordered use_nl(c) index(e) index(c)*/
e.사원번호, e.사원명, e.입사일자,
c.고객번호, c.고객명, c.전화번호, c.최종주문번호
from 사원 e, 고객 c
where c.관리사원번호 = e.사원번호
and e.입사일자 >= '19960101'
and e.부서코드 = 'Z123'
and c.최종주문금액 >= 20000
예시1)
ROWS ROW Source Operation
---- -------------------------------------------
5 NESTED LOOPS
3 TABLE ACCESS (BY INDEX ROWID) OF '사원' (TABLE)
2780 INDEX(RANGE SCAN) OF '사원_X1' (INDEX)
5 TABLE ACCESS (BY INDEX ROWID) OF '고객' (TABLE)
8 INDEX(RANGE SCAN) OF '고객_X1' (INDEX)
예시 2)
ROWS ROW Source Operation
---- -------------------------------------------
5 NESTED LOOPS (cr=2732 pr=386 pw=0..)
2780 TABLE ACCESS (BY INDEX ROWID) OF '사원' (TABLE) (cr=166 pr=2 pw=0..)
2780 INDEX(RANGE SCAN) OF '사원_X1' (INDEX) (cr=4 pr=0 pw=0..)
5 TABLE ACCESS (BY INDEX ROWID) OF '고객' (TABLE) (cr=2566 pr=384 pw=0..)
8 INDEX(RANGE SCAN) OF '고객_X1' (INDEX) (cr=2588 pr=383 pw=0..)
cr : 논리적인 블록 요청 횟수, pr : 디스크에서 읽은 블록 수, pw : 디스크에 쓴 블록 수
버전이 올라가며 오라큼에서 NL 조인 성능을 높이기 위해 아래 기능을 도입했다. 두 기능 모두 읽는 블록마다 건건이 I/O call 발생을 줄이기 위해 고안되었다.
테이블 Prefetch
인덱스를 이용해 테이블을 액세스하다가 디스크 I/O가 필요해지면, 이어서 곧 읽게 될 블록까지 미리 읽어서 버퍼캐시에 적재하는 기능
Inner 테이블에 대한 디스크 I/O 과정에서 테이블 prefetch 기능이 작동할 수 있음. nlj_prefetch
, no_nlj_prefetch
힌트를 이용할 수 있다.
배치 I/O
디스트 I/O call을 미뤘다가 읽을 블록이 일정량 쌓이면 한꺼번에 처리하는 기능
inner 테이블에 대한 디스크 I/O 과정에서 배치 I/O 기능이 작동할 수 있음. nlj_batching
, no_nlj_batching
힌트 사용 가능.
오라클 11g에서 모두 나올 수 있는데 inner 테이블을 모두 버퍼캐시에서 읽는다면 어떤 방식으로 수행하든 성능 차이x, 출력 순서 같음. 일부를 디스크에서 읽으면 정렬 차이가 생길 수 있으므로, ORDER BY 명시하면 좋음.
-- 인덱스 PRA_HST_STC_N1 : SALE_ORG_ID + STRD_GRP_ID + STRD_ID + STC_DT
select *
FROM PRA_HST_STC a, ODM_TRMS b
WHERE
a.SALE_ORG_ID = :sale_org_id
AND a.STRD_GR_ID = b.STRD_GRP_ID
AND a.STRD_ID = b.STRD_ID
AND b.TRMS_DT = :trms_dt
ORDER BY a.STC_DT desc