본문 바로가기

ORACLE

OUTTER JOIN과 JOIN에서의 드라이브

CUSTOMER라는 테이블과 ORDER라는 테이블이 있다고 가정.

CUSTOMER에는 custname과 zip-code,custno(pk)

index는 zip-code 건수는 200만건


ORDER에는 orderno(pk),orderdate,orderprice,custno,ordername가 있다고 가정.

index는 custno+orderdate 건수는 3천만건


특정지역에 사는 고객이 주문한 주문내역을 1개월치를 뽑는다고 할때


1.select B.custname, A.ordername

from order A, cust B

where A.custno = B.custno(+)

and B.zip-code = :v1

and A.orderdate like '200504%'



2.select B.custname, A.ordername

from order A, cust B

where A.custno = B.custno

and B.zip-code = :v1

and A.orderdate like '200504%'


의 차이를 비교해보면..

1번에서 (+)는 아웃터 조인으로 조인을 했을때 B에 데이터가 존재하지 않더라도

A의 값을 뽑아내고 싶다라는 뜻. 집합으로 따지면 AU(A^B)

A 테이블에 있는 데이터를 무조건 가져와야 하기 때문에 인덱스에 상관없이

무조건 A테이블이 먼저 드라이빙된다. 3천만건의 데이터를 읽어들이게 되는 과정에서

and 절에 있는 A.orderdate like '200504%' 를 이용 인덱스를 타고 싶지만! (-_-)

인덱스가 custno + orderdate로 잡혀있기 때문에 인덱스를 사용하지 못 하고

풀스캔을 하며 그중에서 4월치 데이터를 약 20만건 뽑았다고 가정.


이 20만건의 데이터를 A.custno = B.custno로 B테이블과 20만번의 조인을 시도하고

그중 B.zip-code 가 v1인 것들만 뽑아낸다. (한 100건 나오겄지...)


2.만약 (+)를 없애면??

무조건 A테이블을 먼저 드라이빙 하지 않아도 되기 때문에 옵티마이저가

B 테이블을 먼저 드라이빙하며 잡혀 있는 인덱스 zip-code를 사용한다.

여기서 100건이 나왔다고 가정을 하더라도 혹은 1000건이라도..

이렇게 인덱스를 사용해서 얻어낸 B.custno가 상수로 바뀌면서


where A.custno = B.custno(요것이 상수취급)와 and A.orderdate like '200504%'를

이용하여 A테이블을 뒤지는데 custno+orderdate로 잡혀있는 인덱스를 사용하기

때문에 속도적인 면에서 데이터 양에 따라 수십배 이상 차이가 날 수 있다.