본문 바로가기

카테고리 없음

ORACLE 9i Function Based Index v1.0


ORACLE 9i FUNCTION BASED INDEX 

 

 

1.  필요성

A.   조건절 컬럼에 가공을 가하는 경우 해당 컬럼에 인덱스가 존재해도 사용이 불가능하다. 이를 사용케 하기 위해 FUNCTIOIN BASED INDEX가 필요하다.

2.  예제

A.   USER를 생성하고 권한을 부여

SQL> create user samp identified by samp

  2  default tablespace example

  3  temporary tablespace temp

  4  quota unlimited on example;

 

User created.

        (USER를 생성했다.)

SQL> grant create session,create table,select any table to samp;

 

Grant succeeded.

 

SQL> conn samp/samp

Connected.

 

B.   예제로 사용할 TABLE을 생성

SQL> create table employees

  2  as select employee_id, first_name,last_name from hr.employees;

 

Table created.

C.   AUTOTRACE를 사용하기 위한 준비

 

SQL> @$ORACLE_HOME/rdbms/admin/utlxplan.sql

 

Table created.

(PLANTABLE을 생성하는 스크립트이다.)

SQL> conn /as sysdba

SQL> @$ORACLE_HOME/sqlplus/admin/plustrce.sql

SQL> (PLUSTRACE ROLE을 생성하는 스크립트이다.)

SQL> drop role plustrace;

drop role plustrace

          *

ERROR at line 1:

ORA-01919: role 'PLUSTRACE' does not exist

 

 

SQL> create role plustrace;

 

Role created.

 

SQL>

SQL> grant select on v_$sesstat to plustrace;

 

Grant succeeded.

 

SQL> grant select on v_$statname to plustrace;

 

Grant succeeded.

 

SQL> grant select on v_$mystat to plustrace;

 

Grant succeeded.

 

SQL> grant plustrace to dba with admin option;

 

Grant succeeded.

 

SQL>

SQL> set echo off

SQL> grant plustrace to samp;

(해당 ROLE SAMP USER에 부여하였다.)

Grant succeeded.

 

SQL>

 

D.   INDEX를 생성 후 AUTOTRACE 로 확인

(주의 : INDEX를 생성할 테이블 데이터가 작은 경우 사용블록이 작은 관계로 INDEX를 타지 않고 FTS (FULL TABLE SCAN) 가 일어날 수 있다. )

 

SQL> desc employees;

 Name                                      Null?    Type

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

 EMPLOYEE_ID                                        NUMBER(6)

 FIRST_NAME                                         VARCHAR2(20)

 LAST_NAME                                 NOT NULL VARCHAR2(25)

 

SQL> create index employees_first_name_idx on employees(first_name);

 

Index created.

(TABLE INDEX 통계수집을 하였다.)

SQL> analyze table employees compute statistics;

 

Table analyzed.

 

SQL> analyze index employees_first_name_idx compute statistics;

 

Index analyzed.

 

SQL> set autotrace traceonly explain

SQL> select * from employees

  2  where first_name = 'Pat';

 

Execution Plan

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

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=16)

   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'EMPLOYEES' (Cost=2 Card=

          1 Bytes=16)

 

   2    1     INDEX (RANGE SCAN) OF 'EMPLOYEES_FIRST_NAME_IDX' (NON-UN

          IQUE) (Cost=1 Card=1)

(인덱스가 있는 컬럼을 가공없이 조건절로 사용하자 정상적으로 INDEX를 타는 걸 확인 할 수 있었다.)

 

 

SQL> select * from employees

  2  where upper(first_name) = 'PAT';

 

Execution Plan

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

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=16)

   1    0   TABLE ACCESS (FULL) OF 'EMPLOYEES' (Cost=2 Card=1 Bytes=16

          )

(위의 경우와 달리 COLUMN에 가공을 가하자 FULL SCAN이 일어난 걸 확인할 수 있었다.)

 

E.   FUNCTION BASED INDEX를 생성후 AUTOTRACE 로 확인

SQL> drop index employees_first_name_idx;

 

Index dropped.

 

SQL> create index employees_first_name_idx on employees(upper(first_name));

 

Index created.

(함수기반 인덱스를 생성했다.)

SQL> analyze index employees_first_name_idx compute statistics;

 

Index analyzed.

(새로 생성된 인덱스에 대해 통계수집을 실시하였다.)

SQL> select * from employees

  2  where upper(first_name) = 'PAT';

 

Execution Plan

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

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=16)

   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'EMPLOYEES' (Cost=1 Card=

          1 Bytes=16)

 

   2    1     INDEX (RANGE SCAN) OF 'EMPLOYEES_FIRST_NAME_IDX' (NON-UN

          IQUE) (Cost=1 Card=1)

(인덱스를 사용한 걸 확인할 수 있다.)

SQL>

 

3.  기타

A.   INDEX 표현식 조회하기

              i.      USER_IND_COLUMNS , USER_IND_EXPRESSIONS 사용

SQL> select index_name,table_name,column_name

  2  from user_ind_columns;                 

 

INDEX_NAME                     TABLE_NAME COLUMN_NAME

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

EMPLOYEES_FIRST_NAME_IDX       EMPLOYEES  SYS_NC00004$

 

SQL> select * from user_ind_expressions; 

 

INDEX_NAME                     TABLE_NAME COLUMN_EXPRESSION    COLUMN_POSITION

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

EMPLOYEES_FIRST_NAME_IDX       EMPLOYEES  UPPER("FIRST_NAME")                1

 

            ii.      dbms_metadata.get_ddl 이용하기

SQL> select index_name,table_name,

  2  dbms_metadata.get_ddl('INDEX',index_name)

  3  from user_indexes;

 

INDEX_NAME                     TABLE_NAME METADATA

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

EMPLOYEES_FIRST_NAME_IDX       EMPLOYEES

                                            CREATE INDEX "SAMP"."EMPLOYEES_FIRST_NAME_IDX" O

                                          N "SAMP"."EMPLOYEES" (UPPER("FIRST_NAME"))

                                            PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATI

                                          STICS

                                            STORAGE(INITIAL 20480 NEXT 20480 MINEXTENTS 1 MA

                                          XEXTENTS 2147483645

                                            PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFF

                                          ER_POOL DEFAULT)

                                            TABLESPACE "EXAMPLE"