2014년 1월 9일 목요일

SQL Max값을 효율적으로 구하기[재직자무료교육/프로그래머교육/구로디지털IT교육,오라클/자바/닷넷/C#/iOS/안드로이드/아이폰교육]

SQL Max값을 효율적으로 구하기[재직자무료교육/프로그래머교육/구로디지털IT교육,오라클/자바/닷넷/C#/iOS/안드로이드/아이폰교육]


다음과 같이 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
 



댓글 없음:

댓글 쓰기