B-Tree와 B+Tree
Last updated
Last updated
Tree구조는 데이터를 계층적으로 표현하는 자료구조이다.
기준에 따라 계층적으로 분류되어있기 때문에 삽입/삭제 수행시 O(logN)시간이 소요된다.
일반적인 Array나 연결리스트 이용해 O(N)이 걸린다.
데이터베이스는 인덱스를 통해 데이터를 분류하고, 삽입/삭제/조회가 많이 일어나는 만큼 Tree구조로 데이터를 관리하기 적합하다.
따라서 데이터베이스는 Tree구조를 적용하는데, 그 중 B-Tree와 B+Tree를 적용하고 있다.
B-Tree는 이진 트리와 다르게 하나의 노드에 많은 정보를 가지고 있는 형태입니다.
그림의 파란부분은 각 노드의 key를 나타내며, 빨간부분은 자식 노드를 가르키는 포인터입니다.
특징
하나의 노드가 두개 이상의 값을 가질수 있음
최대 자식 수의 개수에 따라 1, 2, 3, .. M차 B-tree가 있음
데이터가 정렬된 상태로 유지되어 있음(핵심)
key 값을 이용해 찾고하는 데이터를 트리 구조를 이용해 찾음
균형트리이기 때문에 B-tree는 어떤 값에 대해서도 같은 시간에 결과를 얻을 수 있다
는 균일성
장점을 가짐
B+Tree는 B-Tree에서 개선된 구조로, B-tree와 달리 실제 데이터는 리프노드에만 저장한다.
리프노드들간의 연결되어 있어, 범위 탐색시 B-Tree보다 좋은 성능을 낼 수 있다.
중복 키를 가짐
내부 노드들이 데이터를 가지고 있지 않기 때문에 리프 노드들이 키와 데이터를 모두 가지고 있어야 함
리프 노드를 제외하고 데이터를 담아두지 않기 때문에 메인 메모리를 더 확보해 더 많은 key를 수용할 수 있음
하나의 노드에 더 많은 key들을 담을 수 있기 때문에 트리의 높이는 더 낮아짐
cache hit를 높일 수 있음
해시테이블
탐색 시간이 제일 빠름
모든 값이 정렬되어 있지 않기 때문에, 해시 테이블에서는 특정 기준보다 크거나 작은 값(부등호)을 찾을 수 없음
따라서 기준 값보다 크거나 작은 요소들을 항상 탐색할 수 있어야 하는 DB 인넥스 용도로는 맞지 않음
RedBlack-Tree(RBT)
B-tree와 큰 차이는 하나의 노드가 가지는 데이터의 개수
RedBlack-Tree는 무조건 하나의 노드에 하나의 데이터 요소만 가지고, B-Tree는 하나의 노드에 여러 개의 데이터 요소를 저장(배열처럼 저장되어 있음)함
B-Tree는 같은 노드 상 데이터를 탐색할 때는 포인터 접근이 아닌, 실제 메모리 디스크에서 바로 다음 인덱스의 접근을 함
하지만 RedBlack-Tree는 각 노드마다 무조건 하나의 데이터만 가지기 때문에 데이터를 접근할 때 무조건 참조 포인터로 접근하게 됨
배열
참조 포인터라는 개념이 없고, 모든 데이터가 메모리 상 차례대로 저장되어 있어 접근이 매우 빠름
탐색 속도로만 본다면 B-Tree보다 훨씬 빠름
해시 테이블과 다르게 정렬 상태로 유지할 수있어 부등호 연산에도 문제가 없음
하지만 배열이 B-Tree보다 빠른 것은 탐색
뿐임
배열 내에서 데이터의 저장, 삭제가 일어나는 순간 훨씬 비효율적인 성능이 발생하게 됨
B-Tree의 배열 형식의 접근과 RedBlack-Tree의 참조 포인터 접근
둘다 시간 복잡도는 O(logN)이지만, 이는 알고리즘 처리에 대한 이론적인 시간 계산 방식일 뿐임
물리적, 절대적인 시간 개념으로는 배열 접근이 훨씬 빠름
참조 포인터로 접근
참조 포인터로 메모리에 접근하는 것은 실제 메모리상 순서대로 저장이 되었든 안되었든, 접근하려는 주소를 연산을 통해 직접 알아내어야 함
이는 주소를 알아내는데 CPU가 내부적으로 많은 연산을 하게 됨
배열 형식의 접근
배열은 데이터들이 메모리 공간에 차례대로 저장되어 있으므로 접근할 주소를 바로 알 수 있음
따라서 메모리 주소를 알아내는데 성능 영향이 없음
B-tree도 자식 노드를 접근할 때는 참조 포인터로 접근함
하지만 하나의 노드가 가지는 데이터 개수가 많아질수록 포인터 개수는 확연히 줄어들고, 트리 내에서 데이터가 많아질수록 이러한 차이는 더욱 커짐
결국 포인터 접근 수의 차이로 B-Tree가 RedBlack-Tree보다 탐색 시간이 더 빠름
항상 정렬된 상태로 특정 값보다 크고 작은 부등호 연산에 문제가 없음
참조 포인터가 적어 방대한 데이터 양에도 빠른 메모리 접근이 가능함
데이터 탐색뿐만 아니라, 저장, 수정, 삭제에도 항상 O(logN)의 시간 복잡도를 가짐
MySQL의 DB engine인 InnoDB는 B+tree로 인덱싱을 처리함
InnoDB에서 사용된 B+tree
같은 레벨의 노드끼리는 Linked List가 아닌 Double Linked List를 사용
자식 노드로는 Single Linked List로 연결되어 있음
key의 범위마다 찾아가야할 페이지 넘버(포인터)가 있는데, 해당 페이지 넘버를 통해 곧바로 다음 노드로 넘어감
리프 노드에서 디스크에 존재하는 데이터의 주소값을 구할 수 있고, Linked List 통해 탐색도 가능함
비교 | B-tree | B+tree |
---|---|---|
데이터 저장
모든 내부, 리프 노드들이 데이터를 가짐
리프노드만 데이터를 가짐
검색 속도
모든 노드 검색, 느림
리프노드에서 선형 탐색
키 중복
없음
있음
삭제
내부 노드의 삭제는 복잡하고 트리 변경이 많음
어떠한 노드든 리프에 있기 때문에 삭제가 쉬움
링크드 리스트
존재 x
리프 노드는 링크드 리스트로 저장됨
높이
특정 갯수의 노드는 높이가 높음
같은 노드일 때 B-tree보다 높이가 낮음
사용
데이터베이스, 검색엔진
멀티레벨 인덱스, DB 인덱스