다음과 같이 EMP 테이블에서 10번 부서의 입사일이 가장 최근인 사람과 같은 입사일을 가진 사원의 사번과 급여를 출력하는 예를 생각해보자. 보통 다음과 같은 SQL문을 이용할 것이다.
:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
SQL> select ename, sal
2 from emp
3 where hiredate = (select max(hiredate)
4 from emp
5 where deptno = 10);
ENAME SAL
---------- ----------
MILLER 1300
위의 경우 서브쿼리를 해서 테이블을 두 번 액세스하게 된다. 또한 이 SQL 문은 서브쿼리가 독립적으로 먼저 풀려서 상수가 되므로 결국 HIREDATE = 상수 조건이 되어 이 조건에 맞는 여러 건의 로우가 리턴 된다.
SQL> select max(hiredate)
2 from emp
3 where deptno = 10;
MAX(HIRE
--------
82/01/23
예를 들어 서브쿼리에서 나온 MAX(HIREDATE)의 값이 '82/01/23' 이었다면 최종 풀리는 SQL 문은 SELECT ENAME, SAL FROM EMP WHERE HIREDATE = ‘82/01/23’ 과 같이 풀려서 여러 건의 로우가 같이 나오게 된다.
이번에는 역순 인덱스를 이용한 힌트를 이용해 보도록 하자.
SQL> create index idx_emp_hiredate on emp(hiredate);
SQL> select
2 ename, sal
3 from emp
4 where deptno = 10
5 and hiredate is not null
6 and rownum = 1;
ENAME SAL
---------- ----------
MILLER 1300
이번엔 다음과 같은 질의를 보자
SQL> select max(sal) - min(sal)
2 from emp
3 where deptno = 10;
MAX(SAL)-MIN(SAL)
-----------------
3700
데이터양이 대량인 경우 위질의보다 아래의 쿼리가 좋을 듯 하다.
with a as (
select sal
from emp
where deptno = 10
and sal > 0
and rownum = 1
) , b as (
select sal
from emp
where deptno = 10
and sal > 0
and rownum = 1
)
select a.sal - b.sal from a, b
실제 많은 양의 데이터가 있는 경우 아래와 같은 결과가 나오니 참조 하시길…
SQL> set autotrace on;
SQL> select count(*) from emp3;
COUNT(*)
----------
7340032
SQL> select max(sal) - min(sal)
2 from emp3
3 where deptno = 10;
MAX(SAL)-MIN(SAL)
-----------------
3700
경 과: 00:00:07.85
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=9707 Card=1 Bytes=
26)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP3' (TABLE) (Cost=9707 Card=16
67991 Bytes=43367766)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
43131 consistent gets
42199 physical reads
0 redo size
406 bytes sent via SQL*Net to client
512 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> with a as (
2 select sal
3 from emp
4 where deptno = 10
5 and sal > 0
6 and rownum = 1
7 ) , b as (
8 select sal
9 from emp
10 where deptno = 10
11 and sal > 0
12 and rownum = 1
13 )
14 select a.sal - b.sal from a, b;
A.SAL-B.SAL
-----------
3700
경 과: 00:00:00.01
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=4 Card=1 Bytes=26)
1 0 MERGE JOIN (CARTESIAN) (Cost=4 Card=1 Bytes=26)
2 1 VIEW (Cost=2 Card=1 Bytes=13)
3 2 COUNT (STOPKEY)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (TABLE) (Cost
=2 Card=5 Bytes=35)
5 4 INDEX (RANGE SCAN DESCENDING) OF 'IDX_EMP_SAL' (IN
DEX) (Cost=1 Card=14)
6 1 BUFFER (SORT) (Cost=4 Card=1 Bytes=13)
7 6 VIEW (Cost=2 Card=1 Bytes=13)
8 7 COUNT (STOPKEY)
9 8 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (TABLE) (Co
st=2 Card=5 Bytes=35)
10 9 INDEX (RANGE SCAN) OF 'IDX_EMP_SAL' (INDEX) (Cos
t=1 Card=14)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
400 bytes sent via SQL*Net to client
512 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
댓글 없음:
댓글 쓰기