hongcheol / CS-study

cs지식을 정리하는 공간
MIT License
248 stars 30 forks source link

B-Tree & B+ Tree #96

Open lksa4e opened 3 years ago

lksa4e commented 3 years ago

B-Tree & B+ Tree

디스크 구조의 이해

image

참조 : https://velog.io/@seanlion/btree

B-Tree의 등장

디스크 I/O의 기본 단위는 블록입니다. 디스크로부터 데이터를 읽거나 기록할 때 이를 포함하는 디스크 블록 전체를 메모리로 읽어오고 다시 블록 전체를 디스크에 기록하는 방식으로 디스크 I/O가 일어납니다. 디스크에 접근하기 위한 시간은 다음과 같이 구할 수 있습니다.

디스크 접근 시간 단위는 milli-second 단위인데, CPU로의 접근 시간은 mirco-second나 nano-second 단위입니다. 즉 디스크보다 CPU가 적어도 약 1000배~1000000배 정도 빠릅니다. 이렇게 느린 디스크 I/O를 수행하기 위해서는 색인(index) 구조가 필요합니다. 색인에 주로 쓰이는 것이 바로 *B-Tree 형제들(B트리, B+트리, R트리...)** 입니다.

예를들어 데이터베이스가 있고, Employee라는 테이블이 있다고 가정해 봅시다.

Employee (총 128 byte)

멀티 인덱스

B-Tree

B-트리는 일반적인 트리 구조인 이진 트리에서 확장되어 부모가 더 많은 수의 자식을 가질 수 있게 됩니다. M개의 자식을 가질 수 있도록 설계된 경우, M차 B-트리라고 합니다. 하나의 레벨에 많은 자료가 저장되기 때문에 전체적으로 트리의 높이가 줄어들게 됩니다. 트리의 높이가 줄어든다는 것은 곧 트리의 성능이 높아진다는 것을 의미합니다.(log단위로 성능의 단위가 붙습니다.) 또한 이런식으로 구성된 트리는 always 균형 잡힌 트리, always Balanced Tree 가 되어 검색에서든, 삽입에서든, 삭제에서든 항상 O(logN)의 성능을 보장합니다!

하나의 노드에 이렇게 많은 데이터를 가질 수 있다는 것은 대량의 데이터 처리가 필요한 검색 구조에 큰 장점이 됩니다. 대량의 데이터는 주로 외부 기억 장치에 저장되는데, 외부 기억 장치들은 블럭 단위로 입출력이 일어납니다. 즉 한 블럭이 1024바이트라면 2바이트를 읽어오기 위해서도 1024바이트를, 1000바이트를 읽어오기 위해서도 동일하게 1024바이트를 입출력 비용으로 지불합니다. B-트리는 하나의 노드를 한 블럭 크기 정도로 조절함과 동시에 트리의 균형도 맞춘 로직을 이미 갖추었기에 데이터베이스 시스템의 인덱스 저장 방식으로 유용하게 쓰입니다.

B-Tree의 성립 조건

B-Tree 탐색

B-Tree 는 이진트리와 마찬가지로 작은 값은 왼쪽 서브트리, 큰 값은 오른쪽 서브트리에 이루어져있습니다.
탐색 하고자하는 값을 root 노드 부터 시작해 하향식으로 탐색해 나갑니다.

B-Tree 삽입

차수에 따라 B-Tree 알고리즘이 다릅니다. 아래 예시는 3차(홀수) B-Tree의 예시입니다. image

B-Tree 삭제

삭제는 크게 Leaf노드인 경우와 Leaf노드가 아닌경우로 나누어집니다.

Case 1. 삭제할 노드가 Leaf 노드이며, 삭제하여도 B-Tree 구조를 유지하는 경우에는 그냥 삭제합니다.

Case 2. 삭제할 노드가 Leaf 노드이지만 ,삭제하는 경우 B-Tree 구조를 깨는 경우

image

Case 3. Leaf 노드에 위치하지 않는 데이터를 삭제하는 경우

image

B+ Tree

B+ Tree의 특징

image

B+ Tree의 탐색, 삽입, 삭제

탐색

B-Tree와 동일하게 탐색합니다. B-Tree와 다르게 Leaf 노드가 순차적으로 linked list를 구성하고 있어, 순차적 처리가 가능합니다.

삽입

삽입의 과정도 B트리와 매우 유사하지만 리프노드에서 최대 key개수를 초과할 때가 다릅니다.

Case 1. 분할이 일어나지 않고, 삽입 위치가 리프노드의 가장 앞 key 자리가 아닌 경우

Case 2. 분할이 일어나지 않고, 삽입 위치가 리프노드의 가장 앞 key 자리인 경우

Case 3. 분할이 일어나는 삽입과정

삭제

삭제과정 역시 기존 B트리와 유사합니다. 하지만 삭제할 key k는 무조건 리프노드에 존재하는 점, k를 삭제하기 위해 검색하는 과정에서 index에 존재할 수 있다는 점이 다릅니다.

Case 1. 삭제할 key k가 index에 없고, 리프노드의 가장 처음 key가 k가 아닌경우

기존의 B트리 삭제과정과 동일합니다.

Case 2. 삭제할 key k가 리프노드의 가장 처음 key인 경우

1) Index 부분은 다른 key 값을 찾는데 사용될 수 있기 때문에 leaf node의 값이 삭제되어도 삭제하지 않습니다.
2) 재배치할 경우 index 부분의 node의 key 값은 변하지만 tree 구조는 변하지 않습니다.
3) 합병을 할 경우 index 부분에서도 key 값을 삭제합니다.

참조 및 자세한 설명 : https://velog.io/@emplam27/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-B-Plus-Tree


B-Tree & B+ Tree 간단비교

공통점

  1. 모든 leaf의 depth가 같다

  2. 각 node에는 k/2 ~ k 개의 item이 들어있어야 한다.

  3. search가 비슷하다.

  4. add시 overflow가 발생하면 split 한다

  5. delete 시 underflow가 발생하면 redistribution하거나 merge 한다.

차이점

  1. B-tree의 각 노드에서는 key 뿐만 아니라 data도 들어갈 수 있다. 여기서 data는 disk block으로의 포인터가 될 수 있다. B+tree는 각 node에서는 key만 들어가야 한다. 그러므로 B+tree에서는 data는 오직 leaf에만 존재한다.

  2. B+tree는 B-tree와는 달리 add, delete가 leaf에서만 이루어진다.

  3. B+ tree는 leaf node 끼리 linked list로 연결되어 있다.

lksa4e commented 3 years ago