Skip to main content

Command Palette

Search for a command to run...

[자료구조] B-tree

Updated
•3 min read•View as Markdown

B-tree와 B+tree

B-tree란?

: 이진트리를 확장한 자료구조 탐색 성능을 높이기 위해 평소에 데이터들의 높이를 균형있게 유지하는 Balanced Tree의 일종이다.
https://media.geeksforgeeks.org/wp-content/uploads/20200506235136/output253.png

  • 노드에는 2개 이상의 데이터(key)가 들어갈 수 있다.
  • 하나의 노드가 가질 수 있는 자식의 최대 숫자가 2보다 크다.
  • 모든 단말(leaf) 노드는 같은 레벨에 있어야 한다. 항상 균형을 유지한다 (균형 잡힌 트리).
  • 최대 M개의 자식을 가질 수 있는 B 트리를 M차(M-way) B트리라고 한다. 내부 노드는 M/2 ~ M개의 자식을 가질 수 있다. (e.g. 3차 B트리 : 1~3개의 자식 노드 가능)
  • 노드 내에 데이터(key)는 floor(M/2)-1개부터 최대 M-1개까지 포함될 수 있다
  • 특정 노드의 데이터(key)가 K개라면, 자식 노드의 개수는 K+1개여야 한다. https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBLi5L%2FbtrdInhxyVP%2Febff3uYkmyoEty5lULR8kK%2Fimg.png 위의 그림은 3차 B 트리로, 각 노드에 데이터(key)와 그 자식들을 가리키는 포인터가 있다.
  • 노드 안에서 데이터(key)는 항상 정렬된 상태를 유지한다.
  • 이진 탐색 트리(BST)와 마찬가지로, 노드의 각 key의 왼쪽 자식은 자신보다 작고 오른쪽 자식은 자신보다 크다.

    그래서 왜 쓰는데?

    일반적인 트리인 경우 탐색하는데 평균적인 시간 복잡도로 O(log N)을 갖는다. 트리가 편향된 경우가 문제인데, **최악의 시간복잡도로 O(N)을 갖게 된다. 이러한 트리의 단점을 보완하기 위해 트리가 편향되지 않도록 항상 균형을 유지하는게 B 트리다. 자식들의 밸런스를 잘 유지하면 최악의 경우에도 O(logN)**의 시간이 보장된다.

    B 트리 연산들

    탐색

    https://www.cs.usfca.edu/~galles/visualization/BTree.html
  • 루트 노드부터 탐색 시작
  • 노드안의 key를 순회하면서 K를 찾고, 존재하면 탐색을 종료
  • K가 존재하지 않는다면, key들과의 값 비교를 한 후 그에 맞는 포인터를 통해 자식 node로 내려간다.
  • leaf node까지 2~3을 반복한다. e.g. 아래 트리에서 값이 14인 key를 찾아보자. https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdbqer3%2FbtrduHVBXeZ%2FZJISmJgbgKJpp1k5UnFYM0%2Fimg.png https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjW9kD%2FbtrdESnKFfM%2FWkRCeAitSffVPiKpBfxkbK%2Fimg.png

    삽입

    균형을 유지해야 하는 B 트리의 성질 때문에, key를 삽입하고 균형이 맞지 않는 경우엔 트리를 변형시켜야 한다.
  • 빈 트리인 경우, 루트 노드를 만들어 K를 삽입한다. root node가 가득 찬 경우, node를 분할하여 leaf node를 생성한다.
  • K가 들어갈 leaf node를 탐색한다.
  • 해당 leaf node에 자리가 남아있다면 정렬을 유지하도록 알맞은 위치에 삽입하고, leaf node가 꽉 차 있다면 K를 삽입한 후 해당 node를 중앙값을 기준으로 분할한다. 중앙값은 부모 node로 합쳐지거나 새로운 node로 생성되고, 중앙값을 기준으로 왼쪽의 key는 왼쪽 자식, 오른쪽의 key는 오른쪽 자식으로 생성된다. e.g. 아까 트리에다 13을 삽입하는 과정 https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsCUPI%2FbtrdBrrwcKW%2FBNlLhjIHg9THT2HgC3araK%2Fimg.png
  • 13이 들어갈 leaf node 탐색
  • 정렬을 유지하는 위치에 삽입
  • 한 노드에 들어갈 수 있는 key 수보다 많이 삽입된 상태이므로, 중앙값(13)을 기준으로 분할하고, 13은 부모 노드로 합쳐준다. 이 과정이 반복된다 https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FupFIB%2FbtrdzN9tLOL%2FxVKPr2jaSIh7pysy5k1Qr1%2Fimg.png https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl8h8w%2FbtrdBqNyhwS%2F3dNoY02TCFniaHdEy5y6sk%2Fimg.png

    시간복잡도

    결국 핵심 연산은 탐색이고, 이 과정이 O(log n) 이기 때문에 삽입과 삭제 또한 O(log n). | | 평균 | 최악 | | --- | --- | --- | | 탐색 | O(log n) | O(log n) | | 삽입 | O(log n) | O(log n) | | 삭제 | O(log n) | O(log n) |

    B+tree란?

  • B-tree의 확장개념
  • 브랜치(중간) 노드에 key만 담아두고, data는 담지 않는 자료구조. 오직 리프 노드에만 key와 data를 저장한다. DB관점에서 생각해볼 때 레코드들은 모두 리프 노드에만 들어간다.
  • 리프 노드끼리 Linked list로 연결되어 있다. 그래서 SQL에서 전체 조회를 할 때에도 속도가 빠르다. https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Bplustree.png/600px-Bplustree.png
  • 데이터의 빠른 접근을 위한 인덱스 역할만 하는 중간 노드(internal node, index node)가 추가로 있음. index노드가 탐색시간을 줄여서 조건부 검색을 빠르게 해준다.
  • 리프 노드를 제외하고는 데이터를 담아두지 않기 때문에 메모리 효율적이다.
  • 하나의 노드에 더 많은 key들을 담을 수 있기 때문에 트리의 높이가 더 낮다.(cache hit를 높일 수 있음)
  • SQL로 테이블 전체 조회를 할 때, B+tree는 전체 리프 노드들에 대해서만 한 번 선형탐색하면 되기 때문에 B-tree에 비해 빠르다. 반면 B-tree의 경우에는 모든 노드를 확인해야 한다.

    InnoDB에서 사용된 B+tree

    https://blog.kakaocdn.net/dn/Cbs9b/btqBVf7DVW2/8JOOKlHiwkoTsqbvbTt7R1/img.png 복잡하긴 하다. 같은 레벨의 노드들끼리는 Double Linked List를 사용했고, 자식 노드로는 Single Linked List로 연결되어있다. key의 범위마다 찾아가야할 페이지 넘버(포인터)가 있는데, 해당 페이지 넘버를 통해 곧바로 다음 노드로 넘어간다.

참고

More from this blog

[JPA] 엔티티 equals 오버라이딩 괜찮을까?

최근에 한 딜레마에 빠졌다. 레포지토리에 대한 테스트 코드를 짜고 있었는데, 확실한 DB 조회 확인을 위해 영속성 컨텍스트를 초기화(em.clear)하면서 문제가 생겼다. 테스트에서 em.clear()을 했을 때의 예시 @BeforeEach 에서 먼저 필드에 더미 데이터를 넣어준다. 추후의 테스트를 편리하게 할 목적의 필드이다. // ... public class MemberRepositoryTest { // ... ...

Oct 26, 20233 min read

[network] JWT

왜 필요한데? 보안 문제 만약 서버와 클라이언트가 서로 유저 정보를 순수 JSON으로 보내게 되면, 이게 유효한 정보인지 확인할 방법이 없다. 만약 악의를 가진 공격자가 유저 ID를 바꿔서 요청을 했을 경우, 서버에선 무슨 일이 일어난 건지 알 방법이 없다. 그래서 유저를 식별할 수 있는 중요한 데이터를 토큰화시켜 주고받게 된다. HTTP의 특징 기본적으로 HTTP 통신은 무상태(Stateless)이다. 매번 사용자가 로그인...

Feb 28, 20234 min read

[network] HTTP & HTTPS

HTTP(Hypertext Transfer Protocol)란? HTTP는 인터넷에서 하이퍼텍스트를 교환하기 위한 통신 규약이다. 대표적으로 주고 받는 데이터 형태는 HTML이다. OSI 7계층중 응용계층에 속하는 프로토콜 TCP/IP 위에서 작동 Request와 Response로 통신 비연결지향(Connectionless) HTTP는 클라이언트가 요청(Request)을 서버에 보내고, 서버는 클라이언트에게 적절한 응답(Response)을 ...

Feb 26, 20233 min read

[database] 트랜잭션

트랜잭션 트랜잭션(transaction)이란? 한 묶음으로 처리되도록 만든 SQL 명령문들을 묶은 작업 단위 대부분의 의미 있는 서비스 처리를 하려면 SQL 명령문 한번 (SELECT, UPDATE, …)만으로는 어렵다. 계좌이체라는 작업을 예시로 들어보자. 만약 X의 돈을 100 감소시키는 UPDATE 문 직후에 서버가 다운되면 어떻게 될까? 더 이상 서버에선 쿼리문을 날리지 못하니, Y에겐 100만큼의 돈이 가지 않고 회사가 X의 돈을 ...

Feb 21, 20232 min read

[database] JOIN

JOIN JOIN이란? 둘 이상의 릴레이션에 흩어져 있는 튜플들을 특정 조건으로 조합하여 하나의 릴레이션을 구성하도록 검색(SELECT)하는 방법. 조인은 릴레이션들의 공통 속성을 기준으로 하므로 테이블들간에 최소한 하나의 속성을 공유하고 있어야 한다. 여러가지 조인 조건에 따라 검색 결과를 다르게 할 수 있다. 아래는 업데이트된 과목, 수강 테이블. 과목번호과목명강의 교수 001컴퓨터구조장성태 002정보보호개론양수미 003...

Feb 10, 20235 min read

wonslee

15 posts