4.인덱스 수립 전략
4.1 인덱스의 선정 기준
- 인덱스가 선정되면 득이 되는 경우와 반대인 경우가 있다.
- 역활이 중복될 경우 안 좋은 영향이 발생할 수 있다.
- 모든 엑세스 형태와 분석을 토대로 이상적인 컬럼 구성과 순서 결정을 통해 단위 인덱스의 역량을 강화시키고, 최소의 인덱스로 모든 엑세스 형태를 만족할 수 있도록 해야한다.
- 가능한 실측자료(엑세스 형태 수집, 분석, 엑세스의 빈도, 처리범위의 크기, 분포도, 테이블의 크기, 엑세스 유형등)를 활용하여 종합적으로 전략적인 결정을 해야한다.
4.1.1. 테이블 형태별 적용기준
- 적은 데이터를 가진 소형 테이블
- 주로 참조되는 역활을 하는 중대형 테이블
- 업무의 구체적인 행위를 관리하는 중대형 테이블
- 저장용 대형 테이블
가) 적은 데이터를 가진 소형 테이블
- 적은 데이터의 의미: 한번의 다중 블록 I/O Call로 모든 데이터를 읽을 수 있는 경우((DB_FILE_MULTIBLOCK_READ_COUNT의 값보다 적은 테이블)
- 한번의 다중 블록 I/O Call로 모든 내용을 읽을 수 있으므로, 인덱스를 통한 스캔과 거의 차이가 없음. 그럼에도 불구하고 생성해야 하는가?
- 인덱스 유무는 옵티마이저의 판단에 많은 영향을 미치는데 특히 조인과 인덱스는 옵티마이저의 결정에 큰 영향을 미침
- 인덱스는 가장 큰 영향요소 이므로 존재 여부에 따라 실행 계획에 큰 영향을 미칠 수 있음.
- 해당 유형의 인덱스는 Nested Loop Join시 내측루프를 주로 수행하므로 많은 횟수가 수행될 수 있음. 약간의 차이가 전체적으로 큰 영향을 미칠 수 있음.
- 권고 : 작은 테이블이라도 PK는 반드시 생성을 권고하며, PK에 의해 참조가 많이 되는 테이블의 경우는 조인 시 효율을 위해 IOT 생성 검토도 필요
나) 주로 참조되는 역활을 하는 중대형 테이블
- 의미: 트랜잭션 데이터들의 행위의 주체나 목적이 되는 개체들로 구성된 테이블들. 모델링에서 키 엔티티로 분류되는 집합임.
- 특징: 좁은 범위의 스캔 또는 조인등에 의해 내측 루프에서 기본키에 의해 연결됨
검색 조건의 형태가 뚜렷하고, 데이터 증감이 별로 없으며, 검색 위주의 엑세스 발생 - 권고
- 기존의 사용중인 인덱스 블록에 사용하는 비율이 낮으므로, 대량 입력 작업이나 오랜 시간이 지났다면 인덱스 Rebuild 권고
다) 업무의 구체적인 행위를 관리하는 중대형 테이블
- 의미: 업무의 구체적인 내용을 담고 있는 테이블.
- 특징
- 조인에서 주로 외측 루프를 담당하고 있음.
- 테이블이 크고, 지속적으로 증가하고 있으므로 많은 인덱스는 입력 시 부하가 가게 하며, 인덱스 구성이 약간만 잘못 되어도 처리 범위가 증가할 수 있음.
- 다양한 엑세스 조건으로 인덱스의 수가 많고 복합 인덱스가 많으며, 다양한 연산자가 존재하여 결합 인덱스의 순서 또한 중요
- 권고
- 인덱스 구성 전략에 따라서 시스템이 미치는 영향이 크므로 절차를 충실히 따라야 함.
이를 위해 테이블에 엑세스 하고 있는 모든 유형을 수집하고, 앞으로 예상되는 형태까지 감안하는 것이 필요
라) 저장용 대형 테이블
- 의미: 로그성 데이터를 관리할 목적으로 생성된 테이블
- 특징: 대량의 데이터를 가지고 있으며, 지속적으로 대량의 데이터가 입력됨.
- 권고
- 갱신이 발생하지 않기 때문에 낮은 PCTFREE 값 지정하는 것이 공간 사용에 유리
- 기본키를 가지는 것은 입력 시 부담이 될 수 있으므로 사용하지 않는 것도 고려. 대신 Unique Index 생성 고려
- 테이블에 파티션을 만들고 파티션 마다 필요한 인덱스(Local Index)를 생성하는 것이 좋음. 오래된 데이터의 경우 파티션 단위로 떼어내기 쉽고 입력이나 검색 시 부담이 적어짐
- 파티션 인덱스 사용 시, 사용 파티션의 인덱스만 사용하는 것도 고려(전체 Local Index를 UNUSABLE 상태로 만든 후, 이후 필요한 파티션의 인덱스만 생성하는 방식)
h3.4.1.2. 분포도와 손익 분기점
- 인덱스 생성의 목적: 전체 집합에서 범위를 줄여 선별된 부분만 엑세스 하고자 함
- 분포도: 전체 집합에서 해당 컬럼으로 조회 시 해당 조건이 차지하는 비율을 의미.
- 손익 분기점: 인덱스는 단일 블록 I/O를 유발하므로 분포도가 높은 경우에는 인덱스가 존재한다 할지라도 사용하지 않을 수 있다.
손익 분기점은 이렇게 인덱스 사용 여부를 결정하는 분포도 값이다. 옵티마이저는 손익분기점 이상이면 인덱스를 사용하지 않고 이하면 사용한다.
- 인덱스의 분포도가 높으면 무조건 인덱스를 생성하지 않는 것이 유리한가?
- 반드시 그렇지 않다. 부분 범위 처리를 할 경우 실제 분포도는 아주 낮아질 수 있다.
h3.4.1.3. 인덱스 머지와 결합 인덱스 비교
- 인덱스 머지(Index Merge): 여러 인덱스가 협력하여 같이 엑세스를 주관
- 장점: 처리 범위가 넓은 경우, 테이블에 엑세스 하여 Filter 하는 부분이 생략됨. 비교하는 조건으로 인덱스만 사용.
- 결합 인덱스: 여러 컬럼을 모아 하나의 인덱스로 만드는 방식.
- 장점: 모든 조건이 인덱스 컬럼에 사용되는 경우 인덱스 머지에 비해 아주 효율적으로 수행될 수 있다.(단, 선두 컬럼의 Equal 연산에서만 적용)
- Index Merge 방식과 결합 인덱스 방식의 연산 차이
h3.4.1.4. 결합 인덱스의 특징
- 인덱스의 첫 번째 컬럼이 조건절에 없다면 일반적으로 인덱스응 사용되지 않음(예외. Oracle 9i 이후 지원되는 Index Skip Scan의 경우는 가능)
- Equal 연산이 아닌 검색 조건이 들어오는 경우(범위 연산), 처리 범위가 크게 증가하여 효율이 크게 저하될 수 있음
h4.가) 분포도와 결합 순서의 상관 관계
ex) 구성
- 테이블: TAB1, 컬럼: COL1, COL2
- 컬럼 COL1: 분포도가 좋지 않음
- 컬럼 COL2: 분포도가 좋음
- 사용된 SQL
SELECT * FROM TAB1
WHERE col1='A'
AND col2 between '113' and '115' |
---|
- 엑세스 방식에 따른 구분
- 분포도가 좋지 않은 COL1 컬럼을 복합인덱스의 선행 컬럼으로 설정한 경우 처리 과정(왼쪽 그림)
1. col1='A' AND col2=112 인 데이터를 B-Tree 방식으로 바로 찾음
2. ROWID를 이용하여 테이블 로우 엑세스
3. 다음 로우를 탐색하여 조건에 만족하면 다시 테이블의 로우를 엑세스하고 그렇지 않으면 스캔 종료(이 경우, 한 번의 랜덤, 2개의 인덱스 로우 스캔) - 분포도가 좋은 COL2 컬럼을 복합인덱스의 선행 컬럼으로 설정한 경우 처리 과정(오른쪽 그림)
1. col2=112 AND col1='A' 인 데이터를 B-Tree 방식으로 바로 찾음
2. ROWID를 이용하여 테이블 로우 엑세스
3. 다음 로우를 탐색하여 조건에 만족하면 다시 테이블의 로우를 엑세스하고 그렇지 않으면 스캔 종료(이 경우, 한 번의 랜덤, 2개의 인덱스 로우 스캔)
- 결론: 인덱스의 모든 컬럼을 Equal 연산으로 처리한 경우 처리량에는 차이가 없음. 단지 Equal 연산만 사용했으므로 필요한 데이터만 읽을 수 있게 되었기 때문.
h4.나) 이퀄(=)이 결합순서에 미치는 영향
- 실제 실무에서는 Equal 연산만으로 처리되지 않고, 다양한 범위 처리 연산(LIKE, BETWEEN, < > 등)이 사용됨
인덱스의 선행 컬럼에 대해 Equal 연산이냐 아니냐는 처리 범위에 크게 영향을 미침
ex) 구성
- 테이블: TAB1, 컬럼: COL1, COL2
- 컬럼 COL1: 분포도가 좋지 않음
- 컬럼 COL2: 분포도가 아주 좋음
- 사용된 SQL
SELECT * FROM TAB1
WHERE col1='A'
AND col2 between '113' and '115' |
---|
- 엑세스 방식에 따른 구분
- 분포도가 좋지 않은 COL1 컬럼을 복합인덱스의 선행 컬럼으로 설정한 경우 처리 과정(왼쪽 그림)
1. col1='A' AND col2=113 인 첫번째 로우를 찾는다.
2. ROWID를 이용하여 테이블의 로우를 엑세스 한다.
3. 다음 로우를 차례로 스캔하면서 col1 !='A' OR col2 > 115 일 때 까지 테이블의 로우를 엑세스 하고 그렇지 않으면 처리를 종료한다.
◎ 이 경우, 첫 번째 컬럼이 Equal 연산이고 두 번째 컬럼에는 정렬이 되어 있으므로 between이 들어갔다 하더라도 필요한 엑세스만 하게 된다.
- 분포도가 좋은 COL2 컬럼을 복합인덱스의 선행 컬럼으로 설정한 경우 처리 과정(오른쪽 그림)
1. col2=113 AND col1='A' 인 첫번째 로우를 찾는다.
2. ROWID를 이용하여 테이블의 로우를 엑세스 한다.
3. col2 > 115 일 때 까지 계속해서 스캔한다. 스캔한 로우는 col1='A' 인지 체크하여 성공하면 ROWID를 이용하여 테이블을 엑세스한다.
4. col2 > 115 이면 처리를 종료한다.
◎ 이 경우, col2 에 대해서는 체크만 하는 이유는 이 컬럼에 대해서는 정렬이 되어있지 않기 때문. 체크로 인해 ROWID를 이용한 테이블 엑세스만 줄어들 뿐이다.
아래의 경우에서 col1 컬럼에 대해서만 인덱스가 있는 경우에서 차이를 볼 수 있다.
11번의 ROWID 스캔에서 3번의 ROWID 스캔으로만 줄고, 실제 인덱스 내부 처리 범위내에서는 효율을 보지 못했다.
- 결론: 인덱스의 처리 범위를 고려해야 하며 컬럼의 분포도를 고려한 인덱스 컬럼 선정 방식은 맞지 않다.
조회 시 사용되는 컬럼에 Equal를 많이 쓰는 경우 처리 범위를 크게 줄여주므로 해당 컬럼을 인덱스 선행 컬럼으로 두는 것이 올바르다.
h4.다) IN 연산자를 이용한 징검다리 효과
- 적용 예
1. 비효율적인 인덱스가 이미 큰 테이블에 대해 사용하고 있는 경우
( 위 예에서 col2, col1 순으로 생성된 결합 인덱스)
2. 올바르게 컬럼 순서로 생성된 인덱스의 쿼리 유형에 상반되는 컬럼 순서의 쿼리가 가끔 사용되는 경우
( col1(=), col2(between) 순서로 들어오는 쿼리가 대부분이고 인덱스고 그 순서로 생성되어있는데, 가끔 col2(=), col1(between) 과 같은 쿼리도 수행되는 경우)
◎ 이 경우, 새롭게 인덱스를 생성하는 것은 인덱스의 중복 투자이므로 올바르지 않음. IN 연산자를 통해 기존 인덱스 만으로도 효율적인 결과를 가져올 수 있음
- 사용 예제
- 기존의 between 연산을 이용한 경우(왼쪽 그림)
col2 컬럼 기준으로 넒은 범위 스캔을 한다. col1 컬럼의 필요한 컬럼인 'A'만을 뽑아내지 못한다. 이 경우, 범위에 해당되는 모든 인덱스를 읽으므로 선을 그은것과 같다 하여 '선(line)연산' 이라고도 한다.
- IN 연산을 이용한 경우(오른쪽 그림)
INLIST ITERATOR(111,112)
1. col2=:value AND col1='A' 인 첫번째 로우를 찾는다. 이 때, 인덱스 트리를 탐색하는 과정이 포함된다.
2. ROWID 탐색을 하고 테이블의 데이터를 뽑아낸다.
3. col2!=:value OR col1!='A' 일 때 까지 테이블의 로우를 엑세스하고 만족하지 않으면 다음의 Iterator 값을 뽑아내 1번 과정을 반복한다.
만약 값이 없으면 전체적인 탐색을 종료한다.
◎ 위 연산은 IN이 가지는 연산의 특징으로 col2 , col1 컬럼의 equal 연산을 여러번 수행하여 불필요한 인덱스 값을 읽는 것을 방지한다.
IN 리스트 내부에 있는 데이터들로 인해 필요한 인덱스 값만 읽게 되는데, 해당 인덱스에 점을 찍은것과 같다하여 '점(point)연산' 이라고도 한다.
- 위 IN 리스트를 사용한 쿼리는 다음의 OR를 사용한 쿼리와 거의 동일한 수행방식을 가진다.
SELECT * FROM TAB1 WHERE (COL2=111 AND COL1='A') OR (COL2=112 AND COL1='A') |
---|
h4.라) 처리 범위에 직접적인 영향을 주지 못하는 컬럼의 추가 기준
- 결합 인덱스를 사용하는 쿼리 내부에 equal 연산을 사용하지 않는 컬럼 이후로는 범위를 줄여주지 못함.
(예로써, (A,B,C,D)로 구성된 인덱스에 A(=),B(between),C(=),D(=) 와 같이 사용했을지라도 B 연산에서 범위 연산자를 쓰게 됨에 따라 C,D 컬럼은 인덱스 스캔 범위를 줄여주지 못함)
ex) 테이블 구성 - col1: equal(=) 연산이 사용됨.
- col2: 사용되지 않거나, 범위 연산자(like, between, < , > 등)이 사용됨.
- col3: 다양한 처리 연산이 사용됨
- 사용 쿼리
SELECT * FROM TAB1
WHERE A='2' AND C='61' |
---|
- 사용 예제
- (A+B) 컬럼에 복합인덱스를 만든 경우(왼쪽 그림)
1. A 컬럼에 대해서는 인덱스가 존재하므로 A='2' 인 모든 노드를 탐색한다.
2. 그러나 C 컬럼에는 인덱스가 없으므로 ROWID를 통한 테이블 억세스으로 테이블 데이터에서 C 컬럼을 뽑아내 C='61' 것을 필터링 한다.
3. 테이블 내부에서 필터링해서 조건에 맞는 것만 출력한다. 이 과정은 인덱스 스캔이 종료될때 까지 계속 수행된다.
◎ 인덱스 탐색 결과 나온 5건에 대해 모두 ROWID를 통한 테이블 엑세스를 한다. 위 경우 총 5번의 테이블 스캔을 한다.
- (A+B+C) 컬럼에 복합인덱스를 만든 경우(오른쪽 그림)
1. A 컬럼에 대해서는 인덱스가 존재하므로 A='2' 인 모든 노드를 탐색한다.
2. 앞선 B 컬럼의 검색 조건 부재로 C 컬럼이 인덱스 검색 범위를 줄여주진 못하나, 값은 존재하므로 C='61' 인 것을 필터하는 부분을 인덱스 내부에서 해결한다.
3. 인덱스 내부에서 필터링해서 조건에 맞는 것만 ROWID를 통한 테이블 억세스로 값을 뿌려준다.
◎ 인덱스 탐색 결과 나온 5건에 대해 필터를 통해 걸리진 1건에 대해서만 ROWID를 통한 테이블 스캔을 한다. 위 경우 총 1번의 테이블 스캔을 한다.
4.1.5. 결합 인덱스의 컬럼 순서 결정 기준
< 컬럼 순서를 결정하는 우선 순위 >
- 1단계: 항상 사용하는가?
- 2단계: 항상 '='로 사용하는가?
- 3단계: 어느 것이 더 좋은 분포도를 가지는가?
- 4단계: 자주 정렬되는 순서는 무엇인가?
- 5단계: 부가적으로 추가시킬 컬럼은 어떤 것으로 할 것인가?
[ 상황 가정 ] : C1, C2, C3, C4 컬럼들에 대해 복합인덱스 컬럼 순서를 어떻게 결정할 것인가?
\- 아래는 쿼리가 사용하고 있는 쿼리 조건의 목록임
1. C1(=), C2(BETWEEN), C3(=)
2. C2(=), C3(BETWEEN), C4(>)
3. C1(=), C2(=), C3(LIKE)
4. C1(=), C2(=), C4(>)
▶ 1단계: 항상 사용하는가?
\* 컬럼의 사용 횟수: C2(4회), C1(3회), C3(2회), C4(2회)
\- 추가 가정: C1 컬럼의 카디널러티가 낮아서 해당 컬럼이 없는 경우에 대해서는 Index Skip Scan 사용하도록 가정
두 번째 경우에서 C2의 경우에서 Equal 연산이 사용되므로 C1 케이스에서 \+1 해서 총 4회 사용으로 가정
- 최종 후보: C1, C2
▶ 2단계: 항상 '='로 사용하는가?
* Equal 연산 사용 횟수: C1(3회), C2(3회)
- C2 컬럼의 경우 첫 번째 경우에서 Between 연산을 사용하므로
- 결과: C1+C2
▶ 3단계: 어느 것이 더 좋은 분포도를 가지는가?
\* 분포도를 고려 및 사용 가능한 추가 연산 형태(예로써 Between을 IN으로 변환 가능한 경우) C1, C2 컬럼의 순서를 추가 검토
\* 이후에 발생할 상황 추이 후 검토
- 엑세스 형태를 수집할 때 현재 사용하고 있는 인덱스 뿐만 아니라 앞으로 등장할 것으로 예측되는 엑세스 형태도 같이 추출
\- 앞으로 어떤 컬럼이 Equal 연산 외에 다른 연산을 사용할 지 검토
▶ 4단계: 자주 정렬되는 순서는 무엇인가?
\* 정렬을 요구하는 구문의 사용 시, 정렬 순서 조사 후 검토. 정렬 시 앞단에 나오는 컬럼을 우선적으로 두는 것이 맞다.
▶ 5단계: 부가적으로 추가시킬 컬럼은 어떤 것으로 할 것인가?
* C3, C4 컬럼의 경우 모든 조건들이 처리 범위를 줄여주는 형태는 아님. C3, C4간의 우선 순위 선정 필요
1. C1(=), C2(BETWEEN), C3(=) : C3이 C4 앞에 오는 것이 유리
2. C2(=), C3(BETWEEN), C4(>): 순서 관계 없음
3. C1(=), C2(=), C3(LIKE): C3이 C4앞에 오는 것이 유리
4. C1(=), C2(=), C4(>): C4가 C3 앞에 오는 것이 유리
- 위의 단순한 결과대로라면 (C1+C2+C3+C4)의 순으로 인덱스 생성하는 것이 좋음
- 그러나, 4 의 경우가 빈번하게 엑세스 되는 경우라면 (C1+C2+C4) 인덱스를 추가 생성해야할 필요도 있을 것임
- 이 이외에 C3, C4 컬럼의 분포도 또한 고려해서 전체적인 상황을 살펴 결정하는 것이 필요
4.1.6. 인덱스 선정 절차
h4.가) 테이블의 엑세스 형태를 최대한 수집
▶ 개발 단계에서의 엑세스 형태 수집
1) 반복 수행되는 엑세스 형태를 찾는다. 반복 수행되는 엑세스는 자신의 수행속도에 반복횟수를 곱한 만큼의 부하를 가져오므로 수행속도에 미치는 영향이 아주 크다.
- Nested Loop Join, Sub-Query, Fetch후 루프 내에서 반복되는 쿼리
2) 분포도가 아주 양호한 컬럼들을 발췌하여 엑세스 유형을 조사한다. 테이블에는 아주 양호한 분포도를 가진 컬럼이 있기 마련이다.
- 인덱스 컬럼 순서를 정할 때등 여러 경우에서 크게 활용될수 있음
3) 자주 넒은 조건이 부여되는 경우를 찾는다. 인덱스는 넓은 범위를 처리하게 될 때 많은 부담을 주게 된다.
\- 전체 범위 처리 시, 넓은 범위 처리는 인덱스 사용 때 수행속도가 좋지 않을 수 있음.
- 처리 범위의 최대 크기와 평균 예상 범위, 자주 사용되는 정렬의 순서, 처리 유형을 수집하면 유용한 자료가 될 것임
4) 조건에 자주 사용되는 주요 컬럼들을 추출하여 엑세스 유형을 조사한다. 빈번하게 사용된다는 것은 시스템 전반에 미치는 영향이 그 만큼 크기 때문에 아주 중요하다.
5) 자주 결합되어 사용되는 컬럼들의 조합 및 정렬되는 순서를 조사한다. 업무적인 측면에서 각 컬럼들간의 상호관계를 잘 파악해 보면 특정 컬럼들끼리 자주 조합하여 사용되는 경합형태를 찾을 수 있다.
- 중심이 되는 컬럼을 찾아 이와 연관되는 컬럼들을 검토
6) 역순으로 정렬되어 있는 경우를 찾는다. End User는 조건의 범위는 넓게 부여하면서 최근의 데이터만 보려고 하는 경우가 많음. 빠른 응답까지 요구함
7) 통계 자료 추출을 위한 엑세스 유형을 조사한다. 통계자료를 추출하는 경우는 대개 범위가 넓다.
- 넓은 범위 처리가 대부분 임. 클러스터나 잘 조합된 결합 인덱스 이용하는 것이 좋음.
▶ 운영 단계에서의 엑세스 형태 수집
* 시점: Test 단계 또는 정상 가동 중인 시스템의 인덱스 교정 시점
1) 어플리케이션 소스 코드에서 SQL을 추출하여 분석용 테이블에 보관한다.
\- 기능: 어플리케이션을 분석하여 SQL 문장을 Repository 에 저장. 손쉽게 SQL 문장을 가져올 수 있음.
- 한계: 동적 SQL 과 같은 쿼리는 가져오는데 한계가 있으며, 수행 횟수와 같은 자세한 사항은 알 수 없음
2) SQL-Trace 파일을 파싱하여 SQL 문장 뿐만 아니라 실행계획, 현재 적용되고 있는 인덱스 , 실행 횟수, 처리 범위등의 매우 상세한 정보 획득할 수 있다.
- 기능: 전체 커다란 trace 결과에 대해 하나의 상세한 레포트도 얻을 수 있으며 상용 SW에 따라 Advice 역할 까지 해주기도 함.
- 한계: 시스템에 큰 부하를 줌. 그러므로 trace 기간은 제한 되어야 하며 그 기간내의 분석 밖에 행할수 없음
3) 공유 SQL 영역에서 직접 SQL을 찾아오는 방법은 보다 SQL 수집을 간편하게 한다.
- 기능: 서버에 부담을 덜 주므로 장기간 수집하는 것이 가능하다.
- 단점: trace에 비해 정보가 빈약하다. 어떤 어플리케이션에서 수행되었는지와 같은
장기간 수집을 하더라도 여전히 모든 SQL 구문 수집하는 것이 어렵다.
▶ 수집된 SQL을 테이블 별로 출력하여 엑세스 형태 기록
- 유사한 형태의 SQL들이 정렬되도록 출력
- SQL문장 별로 정렬하는 것 보다 조건절에 사용된 컬럼별로 정렬하는 것이 보다 유리
-
나) 인덱스 대상 컬럼의 선정 및 분포도 조사
인덱스 대상 컬럼 기준
- 엑세스 유형에 자주 등장하는 컬럼
- 인덱스의 앞부분에 지정해야 할 컬럼
- 기타 수행속도에 영향을 미칠 것으로 예상되는 컬럼
인덱스 대상 컬럼을 선정하고 분포도를 분석한 사례
<그림 1-4-9>
- 매출번호(SALENO): 3년동안 몇건이 발생할 것인지 예상한다.과거 발생자료를 이용한 통계자료 추출 혹은 현업담당자와 협의.
- 판매일자(SALEDATE): 앞서 예상한 월평균 발생건수를 토대로 함.혹은 3년중 휴일을 제외한 날짜를 계산 한 후 총로우수로 나눔. 최대치를 찾는다.
- 판매부서(SALEDEPT)+판매일자: 3년간의 데이터를 부서로 나누어 평균을 산출. 최대, 최소치를 구한다.
- 진행상태(STATUS): 몇가지 종류인지, 어떤 상태에 데이터가 몰려있는지 조사한다.
- 위와같이 하여 최대치와 평균치의 차이가 심하다면 '특기사항'란에 기입한다.
<그림 1-4-10>
다) 특수한 액세스 형태에 대한 인덱스 선정
- 반복되는 액세스형태를 찾아낸다.
- '항상사용되느냐','항상=로 사용되느냐'
- 동률이라면 분포도가 좋은 것이 앞에 오는 것이 유리.
- 1번 액세스 형태인 SALENO+SALEDATE 를 검토해 보면 둘 다 =로 사용되기 때문에 분포도나 정렬 순서를 고려해서 결정하면 된다.
7번 및 11번 액세스 형태를 감안한다면 항상 사용되는 것은 ITEM이다. - SALENO는 1번 액세스에서만 사용되는 것으로 조사되었지만, 혼자서만 사용될 가능성이 높음.
따라서 선두 컬럼에서 배제하기는 어렵다. - ITEM은 좋은 분포도를 가지고 있고, 업무적으로도 중요하며, 앞으로도 자주 사용될 것으로도 보인다.(??)
또한 SALENO 없이도 사용되는 경우가 많으므로 독립된 인덱스에서 선행컬럼이 될 자격을 갖추고 있다. - 11번 액세스에서 ITEM은 주도적인 역할을 하는 것으로 보이진 않으므로 특별한 역할을 부여할 필요는 없어보인다.
- CUSTNO는 평균이 63에 불과하고, 최대가 300 정도이며, 범위처리를 하는 경우가 거의 없이 =로 사용되고 있으므로 CUSTNO 혼자 만으로도 확실한 수행속도를 보장 받을 수 있을 것으로 보임.
- 현재보다 현격하게 데이터량이 증가할 것으로 보인다면 SALEDATE를 인덱스에 추가시키는 것을 검토한다.
라) 클러스터링 검토
- 넓은 범위의 데이터가 자주 액세스 되어 별도의 집계 테이블을 만들지 않고서는 다른 방법이 없는 경우에는 주로 클러스터링을 사용한다.
- 클러스터링은 인덱스와는 달리 분포도가 넓은 것이 유리하다.
- 검색의 속도를 향상시켜주며, 입력,수정,삭제시에는 부하를 준다.
마) 결합인덱스 구성 및 순서의 결정
그룹1
5 SALEDATE(like),STATUS(=60),CUSTNO(like)
8 SALEDATE(like),STATUS(=),group by CUSTNO
6 STATUS(in),[AGENTNO(like)]
- 가장 선두에 와야 할 컬럼은 STATUS 임.
- 방법1: STATUS+SALEDATE, STATUS+AGENTNO (두개의 인덱스 생성)
- 방법2: STATUS+SALEDATE+AGENTNO (1개의 인덱스 생성)
그룹2
7 ITEM(=),SALEDATE(like),SALEDEPT(like)
11 AGENTNO(=),SALEDATE(between),ITEM(like)
- 항상 사용되는 컬럼음 ITEM,SALEDATE 임.
- =로 사용되는 것까지 고려한다면 ITEM+SALEDATE 여야 함.
- 11번의 액세스는 만족스럽지 못하므로 AGENTNO+SALEDATE로 구성된 인덱스를 생성하는 것이 바람직함.
(인덱스 생성의 부담이 있더라도 새로운 인덱스를 생성하는 것을 권장함.)
<그림 1-4-12>
- 모든 액세스에 만족표시(★)가 되도록 한다면 목표달성.
바) 시험생성 및 테스트
- 인덱스 전략이 새롭게 수립되었다면 테스트 과정을 거치는 것이 바람직하다.
- 테스트시 예상했던 실행계획이 쉽게 나타나지 않는다거나, 특정 액세스 형태에 사용해야 할 인덱스를 분명하게 하기 위해서 힌트를 사용해야 한다면 주의사항이 기록한다.
사) 수정이 필요한 애플리케이션 조사 및 수정
- 힌트사용, 인덱스 사용제한, 해제 시키는 수정 필요.
아) 일괄적용
SQL의 수정과 인덱스의 변경을 동시에 일괄적으로 적용해야 한다.