Index Evaluation Metrics
지원되는 액세스 유형
- 일치 질의 형태(exact match query)
- 범위 질의 형태(range query)
액세스 시간
삽입/삭제 시간
공간 오버헤드
Index record가 정렬되어 저장되는 구조
Clustering 색인
정렬색인 정렬 순서와 동일
(데이터 record를 정렬하여 데이터 File을 저장)
데이터 File당 최대 한개
Non-Clustering 색인
데이터 record가 정렬되지 않는 상태 저장
데이터 File에 다수개 존재
탐색키 구성 방법 기준으로 밀집색인/희소색인으로 구분 가능
밀집 색인 (Dense Index)
모든 탐색키 값에 대해 Index record(entry)가 Index에 존재하는 경우
ex) 교수번호를 탐색키로 하여 색인 엔트리가 색인에 존재 -> 밀집 색인
ex) deptName을 탐색키로 하여 색인 엔트리가 색인에 존재 -> 밀집 색인
희소 색인 (Sparse Index)
모든 탐색키 값에 대한 Index record(entry)가 Index에 없는 경우
데이터가 탐색키 기준으로 정렬되어 있지 않은 File에 희소 색인을 구성하는 것은 의미없음
- Pros: 공간을 적게 차지
- Cons: 검색시간이 오래걸림 (entry Index에 없으면 데이터 File을 검색해야 함)
ex) 검색키 기준으로 정렬되어 있다면
희소 색인을 블록에 속하는 가장 적은 값으로 구성
-> 오버헤드: 블록 내 연산 < 메인 메모리 연산
-> 희소색인의 단점 보안
다단계 색인 (Multilevel Index)
Index File을 대상으로 한 단계 상위 Index를 구성
(색인 File에 entry가 많을 경우)Index File은 검색키 기준 정렬
-> 상위 계층의 색인 구성은 희소 색인으로 구성
(크기를 줄임)ex) 원 데이터 및 Index 데이터 모두 블록 단위로 처리
삭제되는 데이터 record가 마지막 record인 경우
ex) 희소 색인인 경우삽입할 키 값을 조회
Index record 순서대로 데이터 record 순서를 정렬하지 않은 Index
(어떤 색인이던 색인 record는 항상 정렬되어야 함)
ex) 포인터는 bucket을 pointing하고 bucket이 record를 pointing하는 구조
(Index record가 간접적으로 데이터 record를 pointing함)
Index를 사용하면 데이터 검색 시간이 향상됨
Index Update는 DB수정에 오버헤드 부과
(-> 파일을 수정할 때 파일의 모든 인덱스를 업데이트하기 때문)
Primary Index는 순차탐색(Sequential scan)에 효율적
Secondary Index는 순차탐색(Sequential scan)에 많은 비용
(+ 이차 색인 레코드 순서대로 데이터 파일을 전체 탐색하면 동일 데이터 블록을 1회 이상 검색 가능)
데이터 변경을 유연하게 대처할 수 있음 (지역적 변경을 하기 때문)
B-tree 색인군
- B-tree
- B⁺-tree
- B*-tree

상기 그림은 n(pointer) n-1(key)인 B⁺ 트리의 예제
Root 노드부터 모든 Leaf node까지의 경로의 길이는 일정
(높이가 높아질 수록 성능 저하)
- Root node와 내부 node: 희소 색인 구조
- leaf node: 밀집 색인 구조
-> leaf node에만 데이터를 저장하고 leaf node가 아닌 node에서는 자식 포인터만 저장
순차 검색을 효율적으로 할 수 있게 됨
Root 노드는 최대 2개 이상의 자식
Root 노드와 Leaf node를 제외한 각 노드는 ⌈ n/2 ⌉ ~ n 개의 자식을 가짐
Leaf node는 ⌈ (n-1)/2 ⌉ ~ n-1 개의 키를 가짐
-> 균형을 위함

데이터의 삽입/삭제 연산으로 인해 특성을 유지하기 위해 트리 재구성을 할 수도 있음

leaf node가 아닌 node에 대하여 Pi는 자식 node에 대한 포인터를 의미 -> page id
leaf node의 Pi는 record에 대한 포인터를 의미 -> record id(page id + slot Number)
- Root node와 내부 node: <pid, value>
- leaf node: <rid, value>

leaf node인 경우에는 (Pi,Ki)가 한 쌍을 이루고 마지막 Pn은 다음 노드를 가리킴
각 포인터는 실제 레코드의 물리적 주소를 가리킴
-> leaf node의 마지막 포인터는 형제 node를 point
내부노드는 포인터에 개수 제약, 리프노드는 탐색 값에 개수 제약 그 이유는?
(노드간에 서로 다른 제약을 사용하는 이유는?)리프노드의 포인트 하나는 sibling(형제)를 연결하는데 항상 사용되므로, 포인트 개수 제한을 하면 underflow 발생 가능성
P1 < K1
Ki-1 ≤ Pi ≤ Ki ( 2 <= i <= n-1)
(equal 관계일시 왼쪽 또는 오른쪽 한 곳에 위치(정의 상 오른쪽))
ex1)블록 크기가 4K이고 탐색 키의 크기가 40bytes라고 가정 하면, 색인 노드에 존재하는 최대 포인터 개수(fanout 이라 고 함)는 약 100개가 되며, 100만 탐색 키를 가지는 B'-트 리 높이는 4 레벨을 가지게 된다. 그 결과 특정 데이터를 검 색하는데 4회 디스크 접근만으로 가능하다. B'-트리는 매 우 뚱뚱한 트리 모습을 가진다.
ex2)예) department 테이블에서 10000개의 레코드를 갖고, 이 중에서 dept_name 값이 '컴퓨터공학과'인 레코드를 검색할 때 인덱스가 없다면 최악의 경우 10000개의 레코드를 모두 검색해야함 , dept_name 필드에 차수가 10인 B+ tree 인덱스가 있다면!
- B+ tree의 높이 = [log10 10000] = 4
- 차수가 10, 검색 키 값의 수가 최대 10000개이므로, B+ tree의 높이는 최대 4를 넘지 않는다
- 최대 4개의 노드만 읽으며 원하는 레코드들을 찾을 수 있다
ex3)B'-트리 높이가 4이고 n=100인 경우, 최대 허용할 수 있는 탐색 키의 개수를 구하면 다음과 같다. 구하는 탐색 키의 가 수를 Y라고 하면
4 ≥ [ log(50)Y ]
관계식이 성립되며, Y=6,250,000이 된다. 6,250,000개 이 하의 탐색 키 값을 가지는 테이블에 대한 색인을 구성하여 디스크 접근 4번 만에 해당 레코드를 검색할 수 있다.

case #1.
leaf 노드가 full 상태가 아니라면 오름차순 정렬에 맞게 삽입
case #2.
리프 노드가 full 상태라면 노드를 분할
case #3.
루트가 쪼개지면 새로운 루트 노드를 생성하되 1개의 키와 2개의 양쪽 포인터로 구성되어야 하며 기존 루트 노드의 중간 key는 새로운 루트 노드에 저장한 뒤 제거


underflow를 해결해야함: Node에 너무 적은 수의 데이터가 존재




(leaf Node가 아닌 Node에는 계속적으로 남아있는 Gold)
비유일 탐색키: 동일 키 값을 가지는 터플이 두개 이상 존재하는 경우
(primary key가 아닌 속성에 대해 B⁺트리를 구성한 경우)
비유일 탐색키가 존재하는 경우 데이터 삭제 연산에 많은 시간 소요



탐색 키가 string 타입인 경우
Index를 구성하고 입력하게 되면 각 데이터가 입력할 때마다 색인에 새롭게 입력된 데이터를 반영하게 됨
-> 디스크 접근 횟수가 많아 비효율적
속성 데이터를 대량으로 입력할 때, 데이터 입력을 우선하고 Index를 구성
B+ Tree Index의 원형
non leaf node에도 레코드로의 포인터를 가지고 있고 Key가 중복되지 않dma
-> 탐색 키가 내부노드에 존재하지 않음

- B Tree 색인이 구현하기 어려움
- B Tree 색인이 트리 깊이가 길어질 가능성이 있음
(record 포인터 값 저장을 하기 때문)- B Tree 색인은 record를 순차적으로 검색하는 경우 트리 내부까지 검색해야 함
- B⁺ Tree 색인은 leaf Node만 검색하면 됨
B⁺ Tree이 상용 시스템에 주로 구현되어 있음
B Tree 색인은 실제로 자주 사용되지 않음
단일 속성만으로 구성되는 색인만이 존재하는 경우
특정 질의에 대해 효율적으로 대처하지 못할 수 있음
다중 색인을 적용하는 경우, 다중 색인의 처음에 나오는 속성에 대하여 exact match 형태가 적용되는 질의문에 효과적임
색인 entry에 탐색 키 속성 외의 다른 속성 값을 함께 저장하는 방식
특정 질의에 효과적일 수 있음
Hash function을 이용하여 File을 구성
Hash function은 검색 키 값을 버킷 주소 값으로 변화
버킷에는 동일한 Hash function 값을 가지는 record가 위치함
ex) Music 13(M)+21(u)+19(s)+9(i)+3(c)=65
65 mod 8 = 1 h(Music) = 1
키가 다르나 Hash값은 동일하다면 같은 bucket에 위치
Hash function은 성능을 결정하는 중요한 요소
해시인덱스 혹은 해시파일의 버킷에 엔트리가 가득 찬 상황에서 해당 버킷에 엔트리가 추가되는 경우

Overflow chaining
가득 찬 버킷에 엔트리가 추가되어 오버플로우가 발생하면
새로운 버킷을 하나 생성하여(오버플로우 버킷) 연결 리스트로 기존 버킷과 연결
Open hashing
오버플로우 버킷을 새로 만들지 않고 다른 버킷의 빈자리에 엔트리를 저장하는 방법
다음순번에 저장: linear probing
재Hash하여 저장: Open hashing
(데이터베이스 환경에는 적합하지 않음(크기/시간))


bucket address Table과 다수개의 bucket으로 운영
Hash function이 동적으로 변함
Hash prefix(해쉬 접두)값은 처음부터 몇개 bit를 사용하는가(값이 아니고 개수임)
Hash prefix의 정보는 버킷 주소 테이블과 각 버킷에 존재
탐색 역시 처음부터 Hash function 값을 통해 구한 i bit만을 참조하여 주소를 구함
버킷 분해
i = 버킷 주소 테이블 접두사 개수 / ij = 버킷 테이블 접두사 개수
- i > ij
버킷 주소 테이블의 하나 이상의 record가 동일한 버킷을 참조하는 경우
-> 버킷을 두 개의 버킷으로 확장 / 버킷 주소 테이블의 크기가 변화하진 않음- i = ij
버킷 j를 참조하는 버킷 주소 테이블의 record가 하나만 있는 경우
-> 버킷을 두 개의 버킷으로 확장하게 되고, 버킷 주소 테이블도 2배로 확장
삭제 후에 버킷이 빈 공간이 되면 buddy(버디) 버킷과 병합 가능
버킷 주소 테이블의 크기가 축소됨
extendable hashing 예제
exact match 질의는 해쉬 또는 정렬 색인을 사용하여 빠른 질의 응답 가능
범위 질의에는 정렬 색인만이 도움됨
ex) bitmap for gender / 수입 level
색인에 의한 공간 오버헤드가 1% 일 정도로 효율적이고 연산이 빠름
ex) 32bit 컴퓨터 기계
- 1,000,000 bits = 125 Kbytes
- 125 Kbyte / 4 byte = 32,000 instructions
삭제된 빈 공간을 채우지 않음
-> 기존 터플에 할당된 번호에 변화가 생기는 비효율성
-> 존재비트맵을 통해 존재비트맵의 i가 0이면 record가 존재하지 않는 것
-> 질의 결과에서 존재비트맵과 중간 결과 비트맵과 and 연산하여 수행
NULL값이 허용된다면 이를 구분하기 위해 NULL값 비트맵을 유지
(NULL의 bit값은 1)
-> 질의 결과에서 NULL값 비트맵과 중간 결과 비트맵을 complement와 and 연산하여 수행