Pi는 non-leaf 노드에서 자식을 위한 포인터이고, leaft 노드에서 레코드나 버킷으로의 포인터이다.
노드에 있는 Search-Key들은 정렬되어 있다.
K1 < K2 < K3 < ... < Kn-1
중복되는 키가 없다고 가정한다.
Leaf Nodes in B+-tree
( 예시 )
리프노드의 마지막 포인터는 형제 노드를 point한다. 이러한 구조는 리프노드를 순차적으로 검색하는 것을 용이하게 한다.
None Leaf Nodes in B+-tree
B+Tree의 내부노드는 leaf node에 대한 다단계 희소색인을 구현한 것이다.
내부 노드 : [P1, K1, P2, K2, ..., Pn-1, Kn-1, Pn]
P1이 가리키는 탐색키 subtree의 값들은 K1보다 작다.
2 <= i <= n-1일 때, Pi가 가리키는 subtree의 모든 search-key들은 Ki-1의 값보다 크거나 같고, Ki 보다는 작다.
Pn이 가리키는 subtree의 모든 search-key들은 Kn-1의 값보다 크거나 같다.B+-Tree Search
"El Said"를 찾는 과정이다.
root node에서 (El Said < Mozart)이므로 두 번째 레벨의 첫 번째 노드를 방문한다.
Einstein < El Said < Gold 이므로 세 번째 레벨의 세번째 노드를 방문한다.
현재 노드에 El Said가 있으므로 포인터를 탐색한다.
B+-Tree Insertion
leaft노드에 탐색 키 값이 있는지 찾는다. 이미 있다면, 레코드를 데이터 파일에 넣는다.
만약 탐색 키 값이 없다면...
레코드를 데이터 파일에 넣는다.
만약 leaf node에 자리가 있다면 leaf node에 (key, pointer) 쌍을 넣는다.
그렇지 않다면 노드를 2개의 새로운 노드로 나눈다. (Split)
Splitting a leaf node
N개의 데이터가 되면 (꽉 차면), 노드 내부의 정렬된 데이터들을 이전의 노드, 새로운 노드로 나눈다.
새로운 노드를 p라고 하고, p안의 최소 key 값을 k라고 하자. (k,P)를 나뉘어진 노드의 부모에 넣는다.
만약 부모가 꽉 차면, split한다. 이는 split이 멈출 때 까지 부모에 계속 전파된다.
최악의 경우, root 노드가 분리되면 트리의 높이가 1 증가한다.
Splitting a non-leaf node : 이미 꽉찬 내부노드 N에 (k,p)를 넣게되면...
(k,p)를 N에 잠깐 넣는다.
N이 P1 ~ P(n/2) 까지 수용한다.
새로운 노드 N'이 P(n/2 + 1) ~ P(n+1) 까지 수용한다.
(K(n/2), N')가 N의 부모노드로 삽입된다.
B+-Tree Deletion
삭제되어야할 레코드를 찾고, 데이터 파일과 인덱스 파일로부터 제거한다.
제거로 인한 underflow를 처리한다.
만약 제거된 데이터의 노드와 형제 노드들이 하나의 노드로 합쳐질 수 있다면, 합친다. (merge, coalesce)
두 노드안의 모든 search-key 값을 하나의 노드에 넣고, 다른 노드를 제거한다.
Pi이가 제거된 노드로의 포인터인 (Ki-1, Pi) 쌍을 모든 부모들로 부터 제거한다.
노드 삭제는 n/2개 이상의 포인터를 가진 노드가 나올 때 까지 위로 연쇄적으로 수행될 수 있다.
만약 부모 노드가 삭제후 오직 하나의 포인터를 가진다면, 그것은 삭제되고 하나의 자식이 루트가 된다.
엔트리 공간이 부족하여 형제노드와 병합할 수 없다면, 포인터를 재분배한다.
노드와 형제노드 사이의 값의 포인터를 재분배하여 둘다 최소 갯수 이상의 엔트리를 가지게 한다.
노드의 부모에 있는 상응하는 search-key값을 갱신한다.
Non-Unique Search Key
RID값을 key속성에 병기하여 모든 키 값을 유일하게 사용한다.B+-Tree File
리프노드에 탐색키-포인터 pair를 저장하는 대신 레코드 포인터를 저장
data insert, delte, update에 의해 색인과 데이터파일이 불일치되는 데이터가 많아질 수 있는데, B+트리 파일 구성은 이러한 문제점을 근본적으로 해결Indices on Multiple Attributes
특정한 유형의 질의에 대해 여러 개의 인덱스를 사용한다.
단일 색인 만이 존재할 때 쓰일 수 있는 전략
각 속성에 대한 인덱스를 통해 얻은 포인터 집합을 교집합한다. (가장 많이 쓰이는 방법)
다중색인은 하나 이상의 속성을 가지는 search key를 가진다.
이때, 다중 색인의 처음에 나오는 속성에 대하여 exact match 형태가 적용되는 질의문에 효과적이다.Covering Indecies
색인 엔트리에 search key 속성외의 다른 속성 '값'을 같이 저장
실제 데이터를 ferch하지 않고도 질의를 위해 값을 내놓을 수 있다.
이차 색인에 특히 효과적임
Dynamic Hashing
Dynamic Hashing
데이터베이스 환경에서 데이터베이스 크기는 항상 변화한다.
이에 적합한 색인 구조는 동적 해쉬이다.
Extendable Hashing
확장 해쉬는 버킷 주소 테이블과 버킷 (실제 레코드가 위치하는 공간)의 두 자료구조를 운영
확장 해쉬에서느 해쉬함수가 동적으로 변하며, 일정 조건이 만족되면 해쉬 함수 치역이 2배로 확장되거나 1/2로 축소될 수 있다. 레코드가 위치하는 버킷이 2개로 분해되거나 2개가 1개로 병합되기도 한다.
해쉬 함수 값 중에서 앞에서 i개의 bit를 사용하여 버킷주소를 결정하며, 버킷 주소 테이블은 i 값을 유지하여야 한다. 버킷에서도 몇 개의 i개의 bit를 사용하여 버킷 주소를 유지하는지 명시하여야 한다.Extendable Hashing Structure
- 각 버킷 j는 Ij값을 가진다.
같은 버킷에 있는 엔트리들은 첫 Ij비트의 값이 같다.
탐색 키 K를 가지는 버킷을 찾기 위해...
H(K)=X를 계산한다.
X의 상위 i개의 비트를 bucket address table에서의 해당 버킷의 위치로 사용하고, 그 곳에 있는 버킷의 포인터를 따라간다.Insertion
탐색키 값 K를 넣기 위해...
버킷 j를 찾는다.
버킷 j에 공간이 있으면, 레코드를 버킷 안에 저장한다.
공간이 없다면...
버킷은 나누어 지고 다시 넣는다.
overflow 버킷이 사용되기도 한다.
탐색키 Kj를 넣을 때 버킷 j를 나누려면...
만약 i > ij라면 (버킷 j로의 여러 개의 포인터가 있음)
새로운 버킷 z를 할당하고, ij = iz = ij+1 한다.
bucket address table의 모든 엔트리들을 update 한다. 이때 이들을 j, 또는 z를 포인트하도록 한다.
버킷 j에 있는 레코드를 제거하고 j나 z에 다시 넣는다.
Kj를 위한 버킷을 넣는다.
만약 i = ij라면... (오직 하나의 포인터만이 buckt j를 가리킴)
만약, i가 한계에 도달하거나, 삽입에 의해 너무 많은 분할이 일어났다면, overflow bucket을 만든다.
그렇지 않으면...
i를 증가하고 bucket address table의 크기를 2배로 늘린다.
buckt address table의 엔트리를 2개로 나누고, 같은 버킷을 포인트 하도록 한다.
Kj를 위한 새로운 bucket address table을 계산하고 삽입한다.Deletion
key 값을 삭제하기 위해서..
버킷을 삭자 삭제한다.
버킷이 비어있게 되면 삭제할 수 있다.
버킷의 병합이 가능하다. (단 buddy 버킷이 같은 ij값을 가지고 같은 ij-1 접두사를 가지고, 이것이 존재 할 경우에만 가능하다.)
bucket address table 크기를 줄이는 것 또한 가능하다.
이것은 비용이 많이 드는 작업이다.Advantage & Disadvantage
Bitmap Index
bitmap Index
비트맵 인덱스는 여러개의 키에 효과적으로 질의하기 위해 설계된 인덱스이다.
도메인 크기가 적은 속성에 대해 적용할 수 있다.
데이터 테이블에 있는 레코드는 0번부터 번호메겨진다.
비트맵은 비트의 배열일 뿐이다.
레코드 갯수 만큼의 비트를 가지고 있다.
비트맵이 value v를 위할 때, 레코드가 그 속성에 대해 v값을 가지면 bit가 1이고 그렇지 않으면 0이다.
비트맵 색인은 여러 속성에 대해 질의할 때 유용하다.
한 개 속성의 질의에 대해서는 딱히 유용하지 않다.
질의는 bitmap 연산을 통해 평가된다.
각 연산은 같은 크기의 2개의 비트맵에 의해 행해지며 결과 비트맵을 결과로 내놓는다.
and, or, not
Storage Overhead
비트맵은 데이터 테이블에 비해 크기가 매우 작다.Deletion and Null Value
Deletion은 적절하게 다뤄져야 한다.
레코드 위치에 유효한 레코드가 있는지 표시하기 위해 existence bitmap이 있다.