happy-developers / dev-interview

1 stars 1 forks source link

[DB] 인덱스란 무엇인가요? #34

Open KIM-KYOUNG-OH opened 1 year ago

KIM-KYOUNG-OH commented 1 year ago

인덱스란 무엇인가요?

키워드

B-Tree, Cardinality, 체인지 버퍼, 인덱스 레인지 스캔, covering index

KIM-KYOUNG-OH commented 1 year ago

인덱스란 색인 같이 데이터 탐색을 속도를 높이는 자료구조 입니다.

인덱스는 별도의 메모리 공간을 사용해서 key-value 형태로 테이블의 데이터를 경량화하여 저장합니다.

B-Tree 자료구조를 사용합니다.

B-Tree 자료구조는 루트 노드, 브랜치 노드, 리프 노드로 구성되고 이진 트리와 다르게 자식 노드를 두 개 이상 가지고 있고 루트 노드를 기준으로 양쪽이 균형있게 관리되는게 특징입니다.

루트 노드와 브랜치 노드에는 자식 노드의 주소가 담겨있고 리프 노드는 인덱스된 컬럼의 값과 데이터가 저장된 메모리 주소를 가리켜서 실제 테이블보다 경량화되어있습니다.

하지만 인덱스는 항상 정렬된 상태로 존재하기 때문에 insert, update, delete 같은 쓰기 작업시 정렬 작업까지 진행해야 하기 때문에 성능이 떨어집니다.

따라서 무턱대고 인덱스를 추가하면 오히려 성능이 약화될 수 있습니다.

따라서 인덱스는 아래와 같은 조건일 때 적용하는 것이 좋습니다.

  1. 카디널리티가 높은 컬럼
    • 유니크한 정도가 높은 컬럼
    • 인덱스는 탐색할 범위를 좁혀주기 때문
  2. 쓰기 작업이 적고 조회 작업이 많은 테이블
    • delete 작업시 데이터를 완전히 삭제하는 게 아니라 사용하지 않음으로 표시합니다.
    • insert시 중간에 값을 추가하고 그 뒤 값들은 주소를 하나씩 뒤로 밀어야하는 오버헤드 발생
    • update는 delete와 insert를 사용해서 구현
  3. 규모가 작지 않은 테이블
    • 규모가 너무 작으면 인덱스 관리 비용만 낭비되고 풀 테이블 스캔을 사용함

👉 인덱스의 쓰기 작업 성능 저하를 보완한 방법은?

innodb 엔진에서는 인덱스의 insert, update, delete 같은 쓰기 작업을 디스크에 바로 적용하지 않고 체인지 버퍼를 사용해서 지연 작업하여 성능을 보완합니다.

버퍼 풀에서 일정한 크기의 버퍼 공간을 확보해두었다가 변경이 생기면 버퍼에 인덱스 변경 정보를 보관해둡니다.

백그라운드 스레드(체인지 버퍼 머지 스레드)를 이용해서 일부 변경 내용을 디스크에 반영합니다.

👉 인덱스가 조회가 빠른 이유는?

첫 번째는 인덱스 레인지 스캔을 사용할 수 있기 때문입니다.

인덱스 레인지 스캔은 테이블 풀 스캔처럼 디스크 테이블 데이터 전체를 탐색하고 필터링하는 방식이 아니라 애초에 탐색할 범위를 좁혀주는 방식이기 때문에 속도가 빠릅니다.

인덱스 레인지 스캔은 트리를 탐색해서 탐색할 범위의 첫 위치를 찾고 조건을 만족하는 동안 연속적으로 데이터를 읽기 때문에 속도가 빠릅니다. 두 번째는 커버링 인덱스가 동작하기 때문입니다.

임의의 쿼리가 인덱스안의 정보만으로 처리될 수 있다면 버퍼만 이용하면 되기 때문에 디스크 I/O를 크게 줄일 수 있습니다.