달력

52025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

WHERE versus HAVING

DB 2006. 7. 16. 02:01

예문을 통해 WHERE를 쓰는 경우와 HAVING을 쓰는 경우의 차이에 대해 알아 보도록 하겠습니다. 어느 방법이 효율이 좋을지 미리 추측을 해보시죠^^;;;
저의 경우 통계 정보를 보기 위해 set autotrace 를  사용했으며 이 부분에 대한 내용은 Oracle 튜닝 강좌를 참고하시기 바랍니다.
참고로 아래 myemp 테이블은 10만건 정도의 레코드를 가지고 있으며 deptno는 외래키로서 인덱스가 걸려 있습니다.

SQL> set autotrace on
SQL> set timing on

아래 질의는 MTEMP 테이블의 데이터를 DEPTNO 별로 그룹핑 하는데 DEPTNO가 10번인 부서원들의 수를 COUNT하는 질의 입니다.

SQL> select deptno, count(*)
  2  from myemp
  3  group by deptno
  4  having deptno = 10;

선택된 레코드가 없습니다.

경   과: 00:00:00.05

Execution Plan
-----------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   FILTER
   2    1     SORT (GROUP BY)
   3    2       TABLE ACCESS (FULL) OF 'MYEMP'


이 경우에는 Table을 FULL SCAN한 후 GROUP BY를 한 후 deptno가 10인 것을 찾기 위해 FILTER를 사용 했습니다. 통계정보는 아래와 같습니다.

Statistics
-----------------------------------------------------
          0  recursive calls
          0  db block gets
        304  consistent gets
        275  physical reads
          0  redo size
        282  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          0  rows processed


이 번에는 having 대신 where절을 이용하여 같은 결과를 만들어 보도록 하겠습니다.

SQL> select deptno, count(*)
  2  from myemp
  3  where deptno = 10
  4  group by deptno;

선택된 레코드가 없습니다.

경   과: 00:00:00.04

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     INDEX (RANGE SCAN) OF 'IDX_MYEMP_DEPTNO' (NON-UNIQUE)

이 경우에는 DEPTNO의 인덱스를 이용하여 부분 검색을 통해 deptno가 10인 데이터를 꺼낸 후 GROUP BY를 시켜 count(*)를 구하였습니다.

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         59  consistent gets
         30  physical reads
       1748  redo size
        282  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          0  rows processed


두 번째의 경우(where를 이용하는 경우)가 deptno에 인덱스가 걸려 있는 경우 약간 효율이 앞선 다고 할 수 있습니다. 시간도 쬐금 앞서구요… 하지만 무조건은 절대 아닙니다. 때에 따라서는 데이터를 먼저 집계를 낸 후 집계된 데이터를 조건을 주어 비교하는 경우도 있으니까요.. 특히 집계된 값이 어떠하다라고 비교 할려면 having구만을 사용해야 합니다. 아래처럼 말입니다.

SQL> select deptno, count(*)
  2  from myemp
  3  group by deptno
  4  having sum(sal) > 2000;

    DEPTNO   COUNT(*)
---------- ----------
        30      49002
        40      16533

2 개의 행이 선택되었습니다.

경   과: 00:00:00.07

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   FILTER
   2    1     SORT (GROUP BY)
   3    2       TABLE ACCESS (FULL) OF 'MYEMP'


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        304  consistent gets
        300  physical reads
          0  redo size
        482  bytes sent via SQL*Net to client
        503  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          2  rows processed
Posted by 알 수 없는 사용자
|