1. 정의
인덱스란 테이블 내의 한 개 또는 여러 개의 컬럼 값과 그 값을 포함하고 있는 행의 논리적 주소를 연관시켜 만들어지는 별도의 저장 구조이다. 
해당 데이터의 검색을 위해 전체 테이블을 읽지 않고 해당 행의 주소를 통하여 직접 접근한다.
생성된 인덱스는 경우에 따라서 하나 이상 사용되기도 하고 전혀 사용되지 않을 수도 있다.
Optimizer에 의해 판단되는 액세스 경로는 주어진 조건, 인덱스의 구성, 통계정보, 클러스터링, Select List, 사용자의 코딩, 힌트(Hint), Optimizer Mode등에 따라서 다양하게 나타나며 이 결정된 액세스 경로에 따라 수행 속도가 좌우된다.
그러므로 양호한 액세스 경로를 보장 받으려면 Optimizer의 액세스 생성 원리에 대한 이해를 바탕으로 좋은 액세스 경로가 생성될 수 있도록 테이블을 설계하고, 적절하고 종합적인 경우를 대비한 인덱스의 지정, 넓은 범위의 처리나 조인의 효율성을 향상하기 위한 클러스터링, 인덱스 적용 원칙에 맞는 SQL의 코딩, 효율적인 SQL의 구사, 통계자료의 주기적인 재생성, 힌트나 Suppressing 기능을 활용하여 Optimizer를 제어하는 등의 노력이 필요하다.

2. 절차

a. 기본 인덱스 설계 (설계 단계)
    1)PK, FK 인덱스 생성
    2)주요 화면에 대한 SQL 구문을 분석하여 인덱스 설계

b. 인덱스 추가 설계 (개발 단계)
    1)SQL 구문 정리 및 조건절 분석
    2)인덱스 적용시 고려 사항
    3)인덱스 크기 산정

c. 인덱스 개선(튜닝)
    1)문제되는 테이블의  SQL 구문 수집
    2)각 SQL이 사용하는 인덱스를 조사하여 개선안 도출
    3)인덱스 개선안 테스트 및 적용

d. 기타 인덱스 활용
   1)Descending Index
   2)Reverse-Key Index
   3)Function-Based Index
   4)Bitmap Index
   5)Index-Organized Table

2.1 기본 인덱스 설계 (설계 단계)

설계단계에서는 데이터가 없고 화면의 내용이 변하므로 정확한 인덱스를 설계할 수 없다.
따라서 변하지 않는 중요 인덱스만을 선정한 후, 80% 이상 개발이 완료된 시점에 인덱스를 재 선정한다.

1)PK, FK 인덱스 생성
-.인덱스 선정에 있어서 기본적으로 Primary Key는 반드시 포함시킨다.
-.Foreign Key는 Foreign Key Constraint를 부여한 경우 Foreign Key 인덱스를 생성한다. (PK와 중복되는 경우는 PK 사용)

2)주요 화면에 대한 SQL 구문을 분석하여 인덱스 설계
-.주요 화면과 SQL 구문 선정 과정은 고객/업무담당자와 함께 한다.
-.자주 조합되어 사용되는 컬럼: 결합인덱스를 생성하는 것이 효율적임.
-.기본키 및 외래키 등 조인의 연결고리가 되는 컬럼
-.선택이나 조인의 기준 컬럼(SQL문의 Where절)
-.ORDER BY,  GROUP BY,  UNION,  DISTINCT 및 SORT조작 시 사용되는 컬럼
-.SQL 구문에 대한 인덱스 선정작업은 구축 작업 완료 후 재작업 한다.
-.분석/설계 단계는 인덱스 크기를 별도로 산정하기보다는 산정된 테이블 크기의 50%를 사용한다.

2.2 인덱스 추가 설계 (개발 단계)

1)SQL 구문 정리 및 조건절 분석
-.코딩된 SQL문을 발췌, 정리하여 SQL 구문을 프로그램별 테이블별로 아래 예와 같이 작성하고, 작성된 내용을 이용하여 조건절을 분석하고, 인덱스 설계서를 작성하여 기본 인덱스 설계와 비교하고 빠진 인덱스를 생성한다
-.조사 대상 프로그램에 대하여 사용하는 SQL 구문 FROM절과 WHERE절을 사용된 그대로 기입한다. (가능하면 전체 프로그램을 대상으로 함)
-.컬럼명은 조건절에서 사용하는 모양 그대로 작성되어야 한다. 즉 컬럼에 함수를 사용했을 경우 함수를 사용한 모습 그대로 작성한다.
-.비교 연산자는 인덱스 생성시 가장 중요한 고려 사항이므로 정확하게 기재한다.
-.A UNION B, A MINUS B, A INTERSECT B 등과 같은 연산은 A와 B를 독립된 SQL문으로 간주한다.
-.서브 쿼리와 Inline View는 독립된 SQL문으로 간주하여 정리한다.
-.WHERE절에 ORDER BY, GROUP BY절 다음의 컬럼들을 순서대로 기입한다

2)인덱스 적용시 고려 사항
-.자주 조합되어 사용되는 경우에는 결합 인덱스를 생성하되, 컬럼 순서 선정에 주의한다.
   -항상 사용되는 것이 첫번째 컬럼
   -항상 사용되는 것이 많다면 ‘=’로 사용되는 것이 첫번째 컬럼
   -분포도가 좋은 컬럼을 우선
   -자주 사용되는 정렬 순서 고려
-.인덱스의 개수는 테이블의 사용 형태에 따라 적절하게 생성하여야 하며, 지나치게 많은 인덱스는 오버헤드를 발생시키므로 특별한 경우가 아니면 5개는 넘지 않도록 한다.
-.중복이 대단히 많은 컬럼은 인덱스에서 제외한다.
-.길이가 40 byte 이상인 컬럼에 대한 인덱스는 피한다.
-.빈번하게 변경되는 컬럼에 대해서는 인덱스 생성을 피한다.
-.정기적으로 Batch 처리를 위해서 필요로 하는 인덱스는 Batch 기간 동안에 생성하고 사용 후 삭제함으로써 인덱스를 유지하기 위한 부하를 최소화하여 온라인 처리의 성능을 향상 시킬 수 있다.
-.인덱스 테이블과 데이터 테이블 I/O수의 합계가 전체 테이블을 스캔하는 I/O수보다 적은 경우에만 성능이 향상된다.

3)인덱스 크기 산정
-.테이블 크기 산정시와 같은 방법으로 별도로 구성된 빈 테이블을 사용하여 인덱스 길이를 구한다.
-.헤더 사이즈를 감안하여 인덱스의 row 평균길이를 구한다.
-.데이터 건수(테이블과 같음)와 길이를 바탕으로, 계산 공식이 반영된 Excel 양식을 이용하여 자동으로 산정한다.

2.3인덱스 개선 ( 튜닝 )

1)문제되는 테이블의 SQL 구문 수집
-.문제되는 테이블을 선정한다.
   -가장 많이 사용되는 테이블 선정
   -데이터 양이 많고 증가량이 큰 테이블 선정
   -인덱스가 너무 많은 테이블 선정 ( 5 ~ 10개 이상 )
   -한 컬럼이 여러 인덱스에 사용되는 테이블 선정
   -고객 의견 반영
-.테이블이 사용하는 SQL 구문을 수집한다.
  (SQL구문 ID 부여 및 중요도 체크)

2)각 SQL이 사용하는 인덱스를 조사하여 개선안 도출
-.SQL 구문의 PLAN 조사 ( autotrace 또는 tkprof 이용 )
-.SQL 구문별 사용 인덱스 컬럼 조사하여 Matrix 작성
   -2006년 3월7일자 인덱스matrix.. 참조(글목록 참조)
-.Matrix를 이용하여 인덱스 개선안 도출
   -사용 빈도수가 적은 인덱스 삭제
   -인덱스 컬럼 순서 조정으로 더 효율적인 경우 순서 조정
   -Full Table Scan 하는 SQL 구문은 인덱스 생성을 고려
   -비슷한 인덱스 병합

3)인덱스 개선안 테스트 및 적용
-.인덱스 개선을 위한 테스트 환경을 마련하여 개선안 테스트
-.개선 전후의 수행시간을 비교하여 개선안 조정
-.인덱스 개선안이 많고 모두 적용하기가 무리이면 확실한 개선 사항이 도출되는 인덱스부터 순차적으로 적용
-.개선안 적용 후 모니터링

2.4기타 인덱스 활용

1)Descending Index
-.DB2와의 호환성을 위해서 Oracle 7점대 버전에서도 “DESC”라는 syntax가 제공되었지만, 이는 실제로 Descending으로 생성되는 것은 아니었다.
-.Oracle 8i부터는 실제로 Index를 Descending으로 생성할 수 있다.

2)Reverse-Key Index
-.Reverse-Key Index란 Index 구성 컬럼의 순서는 그대로 유지하면서 각 컬럼의 데이터(ROWID 제외)를 바이트 단위로 역순으로 인덱싱하는 것을 말한다. (Oracle 8.0부터 적용 가능함)
-.이미 생성된 인덱스의 경우에도 Rebuild를 통하여 변경할 수 있다
-.장점
   ·적은 수의 leaf block에 변경 작업이 집중되는 경우 발생할 수 있는 성능의 저하 회피 가능
   ·Ascending한 자료 축적이 일어나고 낮은 value들이 삭제되어지는 테이블의 경우, 불균형(skewed) 인덱스를 방지함.
   ·RAC 환경에서, 서로 다른 인스턴스에서 같은 Index Block에 Insert 작업시 발생하는 ping을 줄일 수 있음
-.단점
   ·Range Scan 불가능
   ·비트맵 인덱스에 적용 불가
   ·Index-Organized Table에 적용 불가

3)Function-Based Index
-.일반적인 경우, WHERE 조건에서 인덱스 컬럼에 연산을 사용하게되면 인덱스를 사용할 수 없다. Oracle8i부터는 조건절에서의 연산이 필수적인 경우에 인덱스를 사용하려면 Function-Based Index 로 해결할 수 있다.
-.Function-Based Index를 사용하려면 다음과 같이 System Privilege를 부여해야 한다.
   GRANT QUERY REWRITE TO user_name ;
 생성 방법 :
   CREATE INDEX IX_AAA01_02
          ON TB_AAA01 ( REVENUE – COST ) ;
 생성된 index 사용 :
   ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE ;
   SELECT ORDID
      FROM  TB_AAA01
    WHERE ( REVENUE – COST ) > 1000 ;
   ALTER SESSION SET QUERY_REWRITE_ENABLED = FALSE ;
-.Function-Based Index는 Bitmap Index로도 생성 가능하다.

4)Bitmap Index
-.비트맵 인덱스는 Index 컬럼의 각 데이터 종류별로 Bitmap Set을 구성하여 Bit 값으로 Row의 위치를 관리하는 것으로, Oracle 7.3 버전부터 사용 가능하며 Oracle8i에서는 Local Index에 한해서 파티션도 가능하다.
-.컬럼의 분포도에 따라 Bitmap Set 개수가 결정되므로 컬럼의 분포도가 양호할수록 저장 공간이 많이 필요하다. (분포도가 불량일수록 유리함. )
-.Bit 연산으로 인해 Row단위가 아닌 Block-Level Lock이 발생하므로 DML 작업이 적은 업무에 적용하도록 한다.
-.분포도가 불량하고 다양한 컬럼과 OR 연산을 많이 하는 경우에 사용한다.
-.컬럼의 종류가 10 ~ 5개 이하인 경우에 적용한다. ( 성별, 코드, 등급, 유무 등의 컬럼 )
-. “=”, IN ( ) 연산에 유리하며, 범위( <,>,BETWEEN) 연산 및 패턴 조회(LIKE)시에는 인덱스를 사용할 수 없다.
-.대용량 배치 작업시 disable 상태에서 작업하는 것이 권고된다.
-.Bitmap Index의 저장 공간 측정
   -Index 컬럼의 Unique 정도에 따라 크기가 다르므로 실제 값의 종류(Cardinality)가 중요함.
   -Unique 컬럼을 Bitmap Index로 설정할 경우 B*-tree Index보다  1.5 ~ 1.7배 더 많이 소요되고 값의 종류가 1/1000인 경우에는 B*-tree Index 보다 0.15 ~ 0.10 배 정도 적게 소요됨. (추정치)
   -Bitmap Index 크기 = ( A x 150 ) x (B*TREE 인덱스 크기)
 가정) A : 컬럼 분포도 ( 1 / 컬럼 종류 수 )
      분포도 1/1000 기준으로 0.15배 적용 ( 0.15 x 1,000 = 150 )
      B*-tree 인덱스 크기 : 정상적인 Index 산정 크기

5)Index-Organized Table
Oracle 8에 추가된 기능으로, 데이터의 물리적 저장 방식이 Primary Key 를 기준으로 B*-tree 형태로 Row가 저장되는 것이다. 따라서 Index-Organized Table은 ROWID 정보를 갖지 않는다
-.장점
   ·별도의 PK Index의 저장 공간이 필요 없음.
   ·PK 컬럼에 대한 Range Scan, =, IN 연산시 빠름.
   ·Table Full Scan시 데이터가 Ordering 되어 출력됨
-.제약사항
   ·Primary Key가 반드시 있어야 하며, 별도의 Unique Index 추가 불가능. (8.0에서는 Non-unique  Index도 추가 불가능)
   ·Clustering, 병렬 처리, 복제, 분산 불가. (Partition은 가능)
   ·LONG 컬럼 저장 불가. (8i에서는 LOB은 저장할 수 있지만, 이 경우 Partition을 할 수 없음)
   ·Insert 혹은 PK 컬럼 Update시 B*-tree에 대한 부하 발생
-.적용범위
   ·코드 테이블과 같이 수정이 별로 없고 PK 컬럼으로만 Access하는 경우 권고

FROM 네이버 까페 어딘가에서 스리슬쩍~

+ Recent posts