[개발자 대화를 위한 넓고 얕은 CS 지식] 인덱스

Joosi_Cool·2023년 6월 5일
4
post-thumbnail

이번 블로깅에 대해선 인덱스 에 대해 넓고 얕게 알아보자.
개발 공부를 하다보면 인덱스에 대한 이야기는 자주 등장한다. 이에 대해 좀 더 자세히 넓고 얕게 알아보자.

인덱스의 필요성

인덱스는 우리가 알고 있는 것처럼 빠르게 찾을 수 있는 하나의 장치이다. 예를 들어 책의 마지막 장에 있는 찾아보기를 생각하면 된다. 이를 통해서 관련 정보가 어디있는지 빠르게 알아낼 수 있다.

이와 마찬가지로 인덱스를 설정하면 테이블 안에 내가 찾고자 하는 데이터를 빠르게 찾을 수 있다.



B-트리

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

위와 같이 B-트리를 만든다고 가정해보자.
만약 우리가 Data7을 찾는다면 앞에서부터 탐색하면서 7번만에 찾게 될 것이다. 하지만 위와 같이 트리를 만든다면 2번만에 찾을 수 있다.

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

인덱스가 효율적인 이유는 효율적인 단계를 거쳐 모든 요소에 접근할 수 있는 균형 잡인 트리 구조트리 깊이의 대수 확장성 때문이다.

균형잡힌 트리구조는 알겠는데, 대수 확장성은 무엇일까?

  • 대수확정성이란

    트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것을 의미한다.

기븐적으로 인덱스가 한 깊이씩 증가할 때마다 최대 인덱스 항목의 수는 4배씩 증가한다. 이 때문에 여러 노드를 빠르게 탐색할 수 있다.



인덱스 만드는 방법

인덱스를 만드는 방법은 데이터베이스마다 다르며 MySQL과 MongoDB를 예시로 설명해보려 한다.

MySQL

이 경우, 클러스터형 인덱스세컨더리 인덱스 가 있으며, 클러스터형 인덱스는 테이블당 하나를 설정할 수 있다. primary key 옵션을 붙이면 클러스터형 인덱스를 만들 수 있다.
create index... 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있다.

하나의 인덱스만 생성할 것이라면 클러스트형 인덱스를 만드는 것이 세컨더리 인덱스보다 성능이 좋다.
세컨더리 인덱스는 보조 인덱스로 여러 개의 필드 값을 기반으로 쿼리를 많이 보낼 때 생성해야 하는 인덱스이다.
만약 테이블에 age라는 필드값 하나를 보낸다면 클러스터형 인덱스만 필요할 것이다. 하지만 age, name, email 등 다양한 필드를 기반으로 쿼리를 보낸다면 세컨더리 인덱스를 사용해야 한다.


MongoDB

이의 경우 도큐먼트를 만들면 자동으로 ObjectID가 형성되며, 해당 키가 기본키 로 설정된다. 그리고 세컨더리키 도 부가적으로 설정해서 기본키와 세컨더리키를 같이 쓰는 복합 인덱스 를 설정할 수 있다.




인덱스 최적화 기법

인덱스 최적화 기법 또한 데이터베이스마다 조금씩 다르지만, 기본적인 골조는 똑같다. 그래서 이번 설명에서는 MongoDB를 기반으로 설명하겠다. 이를 기반으로 다른 데이터베이스에도 적용할 수 있다.

1. 인덱스는 비용이다.

인덱스는 두번 탐색하도록 강요 한다. 인덱스 리스트, 그 다음 컬렉션 순으로 탐색하기 때문이며, 관련 읽기 비용이 들게 된다.

또한 컬렉션이 수정되었을 때 인덱스도 수정되어야 한다.
이 말이 어렵다면 책의 본문이 바뀌었을 때, 목차도 이에 맞춰 바뀌어야 된다는 점을 생각하면 이해가 쉬울 것이다.

이때 B-트리의 높이를 균형있게 조절하는 비용도 들고, 데이터를 효율적으로 조회할 수 있도록 분산시키는 비용도 들게 된다.
그렇기 때문에 쿼리에 있는 필드에 인덱스를 무작정 다 설정하는 것은 답이 아니다. 또한, 컬렉션에서 가져와야 하는 양이 많을수록 인덱스를 사용하는 것은 비효율적이다.

2. 항상 테스팅하라.

인덱스 최적화 기법은 서비스 특징에 따라 달라진다. 서비스에서 사용하는 객체의 깊이, 테이블 양 등이 다르기 때문이다.
그렇기 때문에 항상 테스팅하는 것이 중요하다. 테스팅을 통해 걸리는 시간을 최소화하려 해야한다.

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

보통 여러 필드를 기반으로 조회를 할 때 복합 인덱스를 생성하는데, 이 인덱스를 생성할 때는 순서가 있고 생성 순서에 따라 인덱스 성능이 달라진다. 같음, 정렬, 다중 값, 카디널리티 순으로 생성해야 햔다.

  • 같음
    어떠한 값과 같음을 비교하는 == 이나 equal이라는 쿼리가 있다면 제일 먼저 인덱스로 설정한다.
  • 정렬
    정렬에 쓰는 필드라면 그 다음 인덱스로 설정한다.
  • 다중 값
    다중 값을 출력해야 하는 필드, 즉 쿼리 자체가 > 이거나 < 등 많은 값을 출력해야 하는 쿼리에 쓰는 필드라면 나중에 인덱스를 설정한다.
  • 카디널리티 순
    카디널리티는 유니크한 값의 정도를 의미한다. 이 카디널리티가 높은 순서를 기반으로 인덱스를 생성해야 한다. 나이와 이메일가 있다고 가정하면 더 유니크한 값은 이메일이다. 이에 대해 인덱스를 먼저 생성해야 한다.




마무리

이번 블로깅에선 인덱스에 대해 알아보았다. 이 블로깅의 목적은 깊게 배우는 것이 아니라 개발자 대회에 낄 정도의 넒고 얕은 지식을 목표로 하고 있다. 이 블로깅을 통해서 전체적인 인덱스 에 대해 잡았으면 좋겠다. 그리고 감을 잡았고 좀 더 깊게 배우고 싶다면 이 블로깅의 키워드를 길로 잡아서 하나씩 공부해 나간다면 매우 도움이 될 것이라고 생각한다.

profile
집돌이 FE개발자의 노트

2개의 댓글

comment-user-thumbnail
2023년 6월 14일

이 내용 읽으시면 깊게 이해할 수 있을겁니다 😉
https://velog.io/@msung99/MySQL-8.0-MySQL-에서의-B-Tree-인덱스를-통한-레코드-스캔-최적화-방식-Index-Scan

추가적으로 InnoDB 의 Optimizer, 실행계획(Execution Plan) 도 꼭 학습하시면 분명히 큰 도움될겁니다..!!

1개의 답글