인덱스

imeline·2024년 1월 23일
post-thumbnail

인덱스의 필요성

  • 인덱스 : 데이터를 빠르게 찾을 수 있는 하나의 장치
    • 예를 들어, 책의 마지막 장에 있는 찾아보기
  • 인덱스는 테이블의 동작속도(조회)를 높여주는 자료구조
    인덱스로 데이터의 위치를 빠르게 찾아주는 역할
    쉽게 예를 들어보면 책 뒷편에 '색인'이 인덱스의 역할과 동일하다고 볼 수 있다.
    -> (예를들어 '홍길동'이라는 단어를 찾고싶으면 색인페이지에서 '홍'으로 시작하거나 'ㅎ'으로 시작하는 색인을 찾아보면 빠르게 찾을 수 있다.)

B-트리

  • 인덱스는 보통 B-트리라는 자료 구조로 이루어짐
    • 이는 루트 노트, 리프 노드, 그리고 루트 노드와 리프 노드 사이에 있는 브랜치 노드로 나뉨

B-트리 예시

  • E를 찾는다고 하면, 전체 테이블을 탐색하는 것이 아니라 E가 있을 법한 리프 노드로 들어가서 E를 탐색하면 쉽게 찾음

업로드중..

  • 트리 탐색은 맨 위 루트 노드부터 탐색이 일어나며, 브랜치 노드를 거쳐, 리프 노드까지 내려옴
  • 57을 찾을 때, 57보다 같거나 클 때까지 〈=를 기반으로 탐색

인덱스가 효율적인 이유와 대수확장성

  • 인덱스가 효율적인 이유 : 효율적인 단계를 거쳐 모든 요소에 접근할 수 있는 균형 잡힌 트리 구조와 트리 깊이의 대수확장성 때문
    • 대수확장성 : 트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것
      기본적으로 인덱스가 한 깊이씩 증가할 때마다 최대 인덱스 항목의 수는 4배씩 증가

인덱스 만드는 방법

  • 인덱스를 만드는 방법은 데이터베이스마다 다름

MySQL 인덱스 만드는 방법

  • 클러스터형 인덱스와 세컨더리 인덱스가 있음

클러스터형 인덱스

  • 테이블당 하나를 설정 가능
  • primary key 옵션으로 기본키로 만들면, 클러스터형 인덱스를 생성
  • 기본키로 만들지 않고 unique not null 옵션을 붙이면, 클러스터형 인덱스로 만들 수 있음
  • 테이블 전체가 정렬된 인덱스가 되는 방식
    -> 테이블 레코드들이, 인덱스 컬럼의 정렬 순서대로 적재되어 있는 것
    -> 찾아보기의 끝, 즉 리프 페이지에는 실제 데이터가 저장되어 있음

세컨더리 인덱스

  • create index ... 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있음
  • 보조 인덱스로 여러 개의 필드 값을 기반으로 쿼리를 많이 보낼 때 생성해야 하는 인덱스
  • 정렬된 별도의 인덱스 페이지를 생성하고 관리
    -> 실제 데이터를 함께 가지고 있지 않음
  • Primary Key 이외에 필요한 정렬 기준이 있을 경우 사용
  • 테이블 당 여러 개를 가질 수 있음

👉🏻 하나의 인덱스만 생성할 것이라면, 클러스터형 인덱스를 만드는 것이 세컨더리 인덱스를 만드는 것보다 성능이 좋음
-> 예를 들어, age라는 하나의 필드만으로 쿼리를 보낸다면 클러스터형 인덱스만 필요하겠죠?
하지만 age, name, email 등 다양한 필드를 기반으로 쿼리를 보낼 때는 세컨더리 인덱스를 사용

MongoDB

  • 도큐먼트를 만들면, 자동으로 ObjecrID가 형성되며, 해당 키가 기본키로 설정
  • 세컨더리키도 부가적으로 설정해서, 기본키와 세컨더리키를 같이 쓰는 복합 인덱스를 설정 가능

인덱스 최적화 기법

  • 데이터베이스마다 조금씩 다르지만, 기본적인 골조는 똑같기 때문에, 특정 데이터베이스를 기준으로 설명해도 무방
  • 이 책에서는 MongoDB를 기반으로 인덱스 최적화 기법을 설명

1. 인덱스는 비용이다

  • 먼저 인덱스는 두 번 탐색하도록 강요
    -> 인덱스 리스트, 그다음 컬렉션 순으로 탐색하기 때문이며, 관련 읽기 비용이 들게 됨
  • 컬렉션이 수정되었을 때 인덱스도 수정되어야 함
    -> 마치 책의 본문이 수정되었을 때 목차나 찾아보기도 수정해야 하듯
    -> 이때 B-트리의 높이를 균형 있게 조절하는 비용도 들고, 데이터를 효율적으로 조회할 수 있도록 분산시키는 비용도 발생
    -> 그렇기 때문에, 쿼리에 있는 필드에 인덱스를 무작정 다 설정하는 것은 답이 아님
    -> 또한, 컬렉션에서 가져와야 하는 양이 많을수록 인덱스를 사용하는 것은 비효율적

2. 항상 테스팅하라

  • 인덱스 최적화 기법은 서비스 특징에 따라 달라짐
    -> 서비스에서 사용하는 객체의 깊이, 테이블의 양 등이 다르기 때문
    -> 그렇기 때문에 항상 테스팅하는 것이 중요

  • explain() 함수를 통해 인덱스를 만들고 쿼리를 보낸 이후에 테스팅을 하며, 걸리는 시간을 최소화해야 함
    -> MySQL에서의 테스팅 수행

EXPLAIN
SELECT * FROM t1
JOIN t2 ON t1. c1 = t2.c1

3. 복합 인덱스는 같음, 정렬, 다중 값, 카디널리티 순이다

  • 보통 여러 필드를 기반으로 조회를 할 때, 복합 인덱스를 생성하는데. 이 인덱스를 생성할 때는 순서가 있고 생성 순서에 따라 인덱스 성능이 달라짐
    -> 같음, 정렬, 다중 값. 카디 널리티 순으로 생성해야 함
  1. 어떠한 값과 같음을 비교하는 ==이나 equal이라는 쿼리가 있다면 제일 먼저 인덱스로 설정합니다.
  2. 정렬에 쓰는 필드라면 그다음 인덱스로 설정합니다.
  3. 다중 값을 출력해야 하는 필드, 즉 쿼리 자체가 2이거나 등 많은 값을 출력해야 하는 쿼리에 쓰는 필 드라면 나중에 인덱스를 설정합니다.
  4. 유니크한 값의 정도를 카디널리티라고 합니다. 이 카디널리티가 높은 순서를 기반으로 인덱스를 생성 해야 합니다. 예를 들어 age와 email이 있다고 해봅시다. 어떤 것이 더 높죠? 당연히 emall입니다. 즉, email이라는 필드에 대한 인덱스를 먼저 생성해야 하는 것입니다.

0개의 댓글