목차

* B-tree 인덱스 설명은 http://wiki.oracleclub.com/pages/viewpage.action?pageId=1507450 에서 사진 및 내용을 인용하였습니다.^^

제2장 인덱스의 유형과 특징

2.1 B-tree 인덱스

2.1.1 B-tree 인덱스의 구조

:——————————————————————————————————

ROWID의 구성

:——————————————————————————————————

2.1.2 B-tree 인덱스의 조작(Operation)

가.인덱스 생성(Creation)

  1. 테이블을 액새스하여 정렬을 수행.
  2. 정렬된 결과를 인덱스 세그먼트의 리프 블록에 기록하기 시작.
  3. 리프블록이 PCTFREE에 도달하여 새로운 블록을 요구하게 되면 브랜치블록을 생성.
  4. 리프블록이 증가함에 따라 브랜치블록도 채워져 가다 블랜치블록이 PCTFREE에 도달하면 새로운 리프블록과 새로운 브랜치블록을 생성할때 루트블록이 생성된다.
  5. 새로운 브랜치블록이 만들어질 때마다 루트블록에 브랜치블록의 DBA정보를 기록한다.
인덱스 블록에 보다 많은 로우를 담기 위해 취할 수 있는방법
CREATE INDEX ord_customer_idx
ON orders (customer_id, sales_id)
COMPRESS 1;

:——————————————————————————————————

나.인덱스 블럭의 분할(SPILT)

:——————————————————————————————————

다.데이터의 삭제 및 갱신

:——————————————————————————————————

라.인덱스를 경유한 검색

 1.루트 블록을 찾는다.   
 2.주어진 값보다 같거나 최소값을 찾는다.(찾는값 >= 인덱스값)
    찾는값 < 인덱스 값 (Lmc에 있는 dba로 이동) 
    찾는 값 = 인덱스 값 (해당 dba로 이동) 
    찾는 값 > 인덱스 값 
       (검색 후 찾는 값 = 인데스 값이면 해당 dba로 이동 그렇지 않으면, 
       찾는 값 < 인데스 값을 만족하는 인덱스 최소값)
 3.리프 블록을 찾을 때까지 ② 의 단계를 반복해서 수행.
 4.리프 블록에서 주어진 값을 가진 키를 찾아 존재하면 ROWID를 이용해 테이블을 액세스하고,
   그렇지 않으면 'No Data found'로 결과 반환 만약, col2의 조건을 'ACC'가 아닌 'AC%'로
    바꾸면 Col1 = 'B'이면서 Col2 = 'AC'보다 같거나 큰 것에서 스캔을 시작, 'AD' 보다 
    작으면 테이블을 액세스하고, 그렇지 않으면 종료한다.

:——————————————————————————————————

마.B-tree인덱스의 문제점

2.2 비트맵(Bitmap) 인덱스

2.2.1 비트맵(Bitmap) 인덱스의 탄생 배경

2.2.2 비트맵(Bitmap) 인덱스의 구조와 특성

구조

특성

» 데이터 웨어하우스 http://100.naver.com/100.nhn?docid=717310

생성절차

  1. 인덱스를 생성하고자 하는 컬럼의 값들을 찾기 위해 테이블 스캔을 한 후
  2. bitmap generator에 의해 컬럼값, start rowid, end rowid , bitmap을 갖는 인덱스 엔트리를 생성한다.
  3. 2단계에서 생성된 Bitmap들을 B-tree구조에 넣기 쉽도록 key값과 start rowid 순으로 정렬한다.
  4. 마지막 단계에서는 정렬된 인덱스 엔트리들을 단순히 B-tree구조로 삽입한다.

제한사항

2.2.3 비트맵(Bitmap) 인덱스의 엑세스

비트맵 인덱스 사용시 실행계획 오퍼레이션

NOT,OR 이 포함된 쿼리에 실행계획

  1. COL1 인덱스에서 '123'인 비트맵을 엑세스하고,COL2인덱스에서 'ABC'인 비트맵을 엑세스하여 감산연산을 수행한다(BITMAP MINUS)
  2. COL2에서 NULL인 비트맵과 1의 결과를 다시 감산연산을 수행한다(BITMAP MINUS)
  3. COL3 < 100 인 비트맵을 읽어 머지(BITMAP MERGE)를 수행하여 하나의 비트맵을 만든다.
  4. 23에서 수행한 결과에 대해 OR연산(BITMAP OR)을 수행하여 조건을 만족하는 최종결과 비트맵을 만들고 ROWID로 변형하여 테이블을 엑세스 한다.

B-Tree 인덱스와 비트맵(Bitmap)인덱스의 비교

2.3 리버스 키 인덱스 (Reverse key index)

2.4 함수기반 인덱스(FBI, Function-Based index)

2.3.1 함수기반 인덱스의 제약사항

2.3.2 함수기반 인덱스의 활용

가.테이블 설계상의 문제를 해결

컬럼의 중간부분을 검색
 create index from_loc_idx on orders (substr(ship_id,5,3));
 create index repair_loc_idx on orders (substr(ship_id,3,2), ord_date);
조인 연결고리 컬럼이 대응하지 않는 경우의 해결
  select ... from item_group x, items y
  where x.class1 || x.class2 || x.class3 = y.group_cd

OR

 select ...
   from item_group x, items y
  where x.class1 = substr(y.group_cd,1,2) 
    and x.class2 = substr(y.group_cd,3,2)
    and x.class3 = substr(y.group_cd,5,3)

위와 같은 경우 다음과 같은 함수기반 인덱스로 해결할 수 있다.

 create index group_cd_idx on item_group(x.class1 || x.class2 || x.class3 );
일자컬럼이 분할 된 경우의 해결
  create index sal_date_idx on sales (sal_yyyy || sal_mm || sal_dd);
데이터 타입이 상이한 조인 컬럼
 create index deptno_idx on emp (to_number(deptno));
조인컬럼이 경우에 따라 달라지는 경우의 조인
 select ... from sales s, departments d
 where d.deptno = (case when sal_type = 1 then 
                           sal_dept
                      else 
                           agent_no
                 end)
   and d.location = 'PUSAN';
 
 create index deptno_idx on sales  
 (case when sal_type = 1 then sal_dept
                         else 
                              agent_no
                         end);
부모테이블의 컬럼과 결합한 인덱스 생성
 select ...
from movement x, movement_trans y
 where x.mov_order = y.mov_order
 and x.deptno = '12310'
 and y.mov_date like '200512%'

위와 같은 sql이 있다면 x.deptno = '12310'이 처리 주관 조건이 된다면 move_date like '200512%'는 체크기능의 역할만 하게 된다. 이때 두개의 조건이 함께 처리 주관조건이 된다면 아주 양호한 수행속도를 얻을 수 있다면 다음과 같은 함수기반인덱스를 이용하여 해결 할 수 있다.

 create or replace function get_deptno(v_mov_order in number)
return varchar2 DETERMINISTIC is
ret_val varchar2(5);
 begin 
select deptno into ret_val
  from movement
 where mov_order = v_mov_order;
return ret_val;
 end get_deptno;
 
 create index dept_date_idx on movement_trans(get_deptno(mov_order),mov_date);

나. 오류데이터의 검색문제를 해결

대소문자나 공백이 혼재된 컬럼의 검색
 create index ename_upper_idx on employees (upper (ename));

== 불필요한 공백을 제거한 후 비교를 해야하는 경우

 create index ename_trim_idx on employees(replace(ename,' '));
접두사를 채워서 검색
 create index call_number_idx 
 on call_data (decode(substr(call_number,1,3),'018','','016')||call_number);

다. 가공처리 결과의 검색

복잡한 계산결과의 검색
 create index order_amount_idx 
 on order_items(item_cd, (order_price-nvl(order_discount,0),0) * order_count));
 select /*+ index_desc(x order_amount_idx) */ *
    from order_items x
 where item_cd = :b1
       and rownum <= 100
 create index sal_amount_idx on sales (last_day(sal_date), sal_amount);
 create index term_idx on activities (expire_date - start_date)
 create index source_length_idx on print_media(text_length(source_text));

라. 오브젝트 타입의 인덱스 검색

길이,폭,높이 세가지 컬럼을 이용하여 부피를 구하는 volume()메소드를 정의

 create type cube AS object
(
length number,
width  number,
heigth number,
member function volume return number DETERMINISTIC
);

create or replace type body cube as 
member function volume return number is
   begin
     return (length * width * height);
   end;
end;

cube유형(TYPE)으로된 CUBE_TAB 테이블을 생성하고, volumn() 메소드로된 함수기반 인덱스 생성

 create table cube_tab of cube;
 create index volume_idx on cube_tab x (x.volume());
 

인덱스를 경유하여 엑세스를 수행

 select * from cube_tab x where x.volume() > 100

마. 베타적 관계의 인덱스 검색

배타적 관계의 유일성 보장
 create unique index official_id_idx 
 on customers(case when cust_type =1 then resident_id else business_id end);
 
 select * from customers
 where (case when cust_type =1 then resident_id else business_id end) = :b1;
 create unique index contract_idx on insurance (
 case when then ins_type = 'A01' then customer_id else null end, 
 case when then ins_type = 'A01' then ins_type     else null end
 );
 insert into contact_person 
 insuran_id, ..., customer_id, ins_type) values (122101, ..., 2101, 'A01');
 
 1row created.
 
 insert into contact_person 
 (insuran_id, ..., customer_id, ins_type) values (122102, ..., 2101, 'A01');
 
 ERROR at line 1;
 unique constraint (OE.CONTRACT_IDX) violated
배타적관계의 결합인덱스
 create index order_deliver_idx1 on order_delivery(
 order_dept, //고정된 선행컬럼
 case when ord_type=1 then delivery_date else shipping_date end), // 중간 컬럼인덱스
 item_type 
 )