본문 바로가기

DIARY

091026 ORACLE SMALL TALK

SQL> get a

1 select /*+ ordered */ e.ename,d.dname

2 from

3 emp e,

4 (select sum(e.sal) sal,e.deptno,d.dname

5 from emp e,dept d

6 where e.deptno = d.deptno

7 group by e.deptno,d.dname) d

8* where e.deptno = d.deptno

 

Rows Row Source Operation

------- ---------------------------------------------------

14 HASH GROUP BY (cr=76 pr=0 pw=0 time=24752 us)

70 NESTED LOOPS (cr=76 pr=0 pw=0 time=18272 us)

70 NESTED LOOPS (cr=4 pr=0 pw=0 time=5963 us)

14 TABLE ACCESS BY INDEX ROWID EMP (cr=2 pr=0 pw=0 time=1576 us)

14 INDEX FULL SCAN EMP_DEPTNO_IX (cr=1 pr=0 pw=0 time=1146 us)(object id 54486)

70 INDEX RANGE SCAN EMP_DEPTNO_IX (cr=2 pr=0 pw=0 time=2036 us)(object id 54486)

70 TABLE ACCESS BY INDEX ROWID DEPT (cr=72 pr=0 pw=0 time=7996 us)

70 INDEX UNIQUE SCAN PK_DEPT (cr=2 pr=0 pw=0 time=2913 us)(object id 51147)

 

오랜만에 잡담이다.

문득 그룹핑되어있는 조인의 순서를 깨버리면 어떤 플랜이 나오나 확인하고 싶었다.

이를테면 A,B 가 GROUP BY 되어있는 구문 ((A,B),C) 를 (A,(B,C)) 로 바꾸는 것이다.

 

위의 플랜은 ORDERED 를 사용해 위와 같은 시도를 하였다.

힌트가 없으면 inline view 의 쿼리를 먼저 실행 후 메인쿼리와 조인을 한다.

그러나 emp가 driving 되면 cost 와 힌트에 따라 다른 operation 이 나올 수 있다.

이 경우는 그룹핑을 깬 결과가 나왔다.

(먼저 group by 되어있는 테이블에 대해 결과집합을 만들지 않았다는 의미)

 

처음 메인쿼리의 emp index 를 읽고 table 에 엑세스 후 다시 emp index 에 엑세스해

앞서 엑세스한 값을 상수값으로 조인을 시도한다.

 

DEPTNO COUNT(*)

---------- ----------

1

30 6

20 5

10 3

 

위의 표는 부서별 직원수이다.

emp 에 엑세스 해 다시 자신의 index 에 엑세스 하는데 조인조건으로 사용하는 것은

emp.deptno 이다.

이 조건은 autotrace 나 explain plan 에서 predicate information 으로 확인할 수 있다.

결과적으로 같은부서에 대해 조인은 모두 성공하므로 null 을 제외한

(6*6) + (5*5) + (3*3) = 36 + 25 + 9 = 70 이다.

이는 위 트레이스와 동일한 결과이다.

 

다음으로 dept 와 join 하게 된다.

dept와 emp는 부/자 관계로 조인은 모두 성공한다.

n:1 관계이므로 결과는 n이 된다.

조인의 결과 ROW 수는 70이 된다.

 

마지막으로 HASH GROUP BY를 하게 된다.

그룹핑의 키는 DEPTNO 이다.

중복된 DEPTNO 가 모두 사라지므로 ROWS 수는 6 + 5 + 3 가 된다.

sum 값은 /*+ ORDERED */ 와 관계없이 정상적인 값을 보이는데 중복된 값이

오퍼레이션 중에 제거되고 남은 값으로 sum 한 것으로 보인다.

제거되지 않았다면 힌트없이 실행한 결과와 다른 값이 나와야 하는데 동일하기

때문이다.

 

오늘 이야기를 한 것은 inline view 가 merging 되면서 비효율적으로 풀리는 경우가

있어 생각해 보았다.