2013년 8월 3일 토요일

ORACLE HINT ACCESS 경로를 변경하는 힌트(FULL) , ORACLEJAVA 강좌, 교육

ACCESS 경로를 변경하는 힌트(FULL)

구로디지털 오엔제이프로그래밍실무교육센터


힌트문(FULL)의 인자로 주어지는 테이블에 대해 FULL SCAN할 것을 지시하는데 FROM절 다음에 테이블명과 Alias를 사용했다면 FULL 힌트에 Alias를 사용해야 하며 FROM절 다음 테이블명 앞에 스키마 명이 사용되었다면(scott.emp) 힌트 안의 FULL에서는 스키마 명은 생략을 해야 한다.

[잘못된 경우

a 아래의 경우엔 FULL(e) 라고 해야 하는데 잘못 됨
select
             ename, sal, job
from    emp e
where   job    = 'CLERK'

a 아래의 경우엔 FULL(EMP) 라고 해야 하는데 잘못 됨.
select
             ename, sal, job
from    scott.emp
where   job    = 'CLERK'


다음과 같은 SQL문장을 보도록 하죠~

먼저 실습용 테이블을 만들자.

==============================================

create table myemp1
(empno number not null primary key,
 ename varchar2(100),
 deptno number,
 addr   varchar2(100),
 sal    number
 )

 create table mydept1
 (deptno nunmber,
  dname  varchar2(100)
  )
 
 insert into mydept1 values (0, '인사팀');
 insert into mydept1 values (1, '회계팀');
 insert into mydept1 values (2, '영업팀');
 insert into mydept1 values (3, '기획팀');
 insert into mydept1 values (4, '교육팀');


-- 실습을 위해 myemp1 2000만건 만들자.
DECLARE
          v_c NUMBER := 1;
BEGIN

          WHILE (v_c <= 10000000) LOOP
                insert into myemp1 values ( v_c, '홍길동'||v_c, mod(v_c, 5), '서울'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '다길동'||v_c, mod(v_c, 5), '부산'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '나길동'||v_c, mod(v_c, 5), '대구'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '나길동'||v_c, mod(v_c, 5), '광주'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
          END LOOP;
          commit;
END;


create index idx_myemp1_deptno on myemp1(deptno)

analyze table myemp1 compute statistics
analyze table mydept1 compute statistics

========================================================

아래는 오라클 11g R2에서 테스트 했습니다.

아무 힌트를 주지 않고 실행 했더니 Index Fast Full Scan을 했다. (index_ffs 힌트 쓴것처럼)

SQL>  select count(*) from myemp1
  2   where deptno = 3
  3    or   deptno = 4;

  COUNT(*)
----------
   4000000

   : 00:00:03.87

Execution Plan
--------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                   |     1 |     2 |  5318  
|   1 |  SORT AGGREGATE       |                   |     1 |     2 |           
|*  2 |   INDEX FAST FULL SCAN| IDX_MYEMP1_DEPTNO |  4000K|  7812K| 
---------------------------------------------------




이번에는 FULL 힌트를 사용해 보자. 데이터가 2000만건 정도 있어서 많이 느리다.

SQL> 1   select count(*) from myemp1
  2   where deptno = 3
  3*   or   deptno = 4


SQL> /

  COUNT(*)
----------
   4000000

   : 00:00:09.92

Execution Plan
--------------------------------------------------------------------|   0 | SELECT STATEMENT   |        |     1 |     2 | 16985   (1)| 00:03:24 |
|   1 |  SORT AGGREGATE    |        |     1 |     2 |            |          |
|*  2 |   TABLE ACCESS FULL| MYEMP1 |  4000K|  7812K| 16985   (1)|


이번에는 or 조건을 하나 더 줘 테스트
검색 속도가 훨씬 빨라졌다

SQL> select count(*) from myemp1
  2  where deptno = 3
  3   or   deptno = 4
  4   or   deptno = 1
  5   or   deptno =0;

  COUNT(*)
----------
   8000000

   : 00:00:01.34

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT      |                   |     1 |     2 |  5346  
|   1 |  SORT AGGREGATE       |                   |     1 |     2 |           
|*  2 |   INDEX FAST FULL SCAN| IDX_MYEMP1_DEPTNO |  8000K|    15M| 


이번에도 FULL 힌트를 주고 테스트 했는데 너무 느리다.

SQL> edit
file afiedt.buf()가 기록되었습니다

  1  select count(*) from myemp1
  2  where deptno = 3
  3   or   deptno = 4
  4   or   deptno = 1
  5*  or   deptno =0
SQL> /

  COUNT(*)
----------
   8000000

   : 00:00:09.93


물론 인덱스 컬럼에 변형을 가해도 FULL 힌트를 사용한 것 처럼 느리다. 조심해야 한다.


SQL> select  count(*) from myemp1
  2  where to_char(deptno) = '3'
  3   or   deptno = 4
  4   or   deptno = 1
  5   or   deptno =0;

  COUNT(*)
----------
   8000000

   : 00:00:09.96

Execution Plan
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     1 |     2 | 17031   (2)| 00:03:25 |
|   1 |  SORT AGGREGATE    |        |     1 |     2 |            |          |
|*  2 |   TABLE ACCESS FULL| MYEMP1 |  6800K|    12M| 17031   (2)|



아래는 index_ffs(인덱스 패스트 풀 스캔)을 이용했더니 많이 개선 되었다.


SQL> select /*+ index_ffs(myemp1 idx_myemp1_deptno) */ count(*) from myemp1
  2  where deptno = 3
  3   or   deptno = 4
  4    or deptno = 0;

  COUNT(*)
----------
   6000000

   : 00:00:01.29

Execution Plan
--------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                   |     1 |     2 |  5334  
|   1 |  SORT AGGREGATE       |                   |     1 |     2 |           
|*  2 |   INDEX FAST FULL SCAN| IDX_MYEMP1_DEPTNO |  6000K|    11M|   

댓글 없음:

댓글 쓰기