본문 바로가기
cs/면접을 위한 CS 전공지식 노트

4-5. 인덱스

by 이쟝 2022. 11. 4.
더보기

2022.09.19 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 1-1. 디자인 패턴(1)

2022.09.20 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 1-1. 디자인 패턴(2)

2022.09.20 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 1-2. 프로그래밍 패러다임(함수형,객체지향,절차적프로그래밍)

2022.09.22 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 2-1. 네트워크의 기초(토폴로지&성능분석 명령어)

2022.09.23 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 2-2. TCP/IP 4계층 모델

2022.09.27 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 2-3. 네트워크 기기(스위치 등)/IP주소

2022.10.02 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 2-4.HTTP

2022.10.04 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 3-1. 운영체제의 구조와 역할 및 컴퓨터의 구조

2022.10.07 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 3-2. 메모리계층 및 메모리 관리

2022.10.10 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 3-3. 프로세스와 스레드(1): 프로세스의 컴파일과정, 상태, 메모리 구조, PCB

2022.10.14 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 3-3. 프로세스와 스레드(2): 멀티프로세싱

2022.10.24 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 3-4. CPU 스케줄링 알고리즘

 

2022.10.27 - [소소한 CS 지식/면접을 위한 CS 전공지식 노트] - 4-1. 데이터베이스의 기본(엔터티의 관계, 데이터 타입 최적화, 관계, 키)

5-1. 인덱스의 필요성

인덱스: 데이터를 빠르게 찾을 수 있는 하나의 장치, 추가적인 쓰기 작업과 저장 공간을 활용해 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조

  • 속성 값을 기준으로 이미 정렬되어 있고, 그에 해당하는 레코드 주소가 있어 바로 데이터 접근이 가능하다.
  • 인덱스 검색을 위한 조건은 WHERE 절에 인덱스로 설정된 컬럼명이 나와야 한다.
  • 인덱스로 설정된 컬럼명이 나와도 인덱스가 사용되지 않는 경우도 존재한다. 
  • 인덱스를 활용하면, SELECT 외에도 UPDATE나 DELETE의 성능이 함께 향상되는 이유는 해당 연산을 수행하려면 해당 대상을 조회해야만 작업을 할 수 있기 때문이다.
// Thomas이라는 이름을 업데이트 해주기 위해서는 Tom을 조회해야 한다.
UPDATE USER SET NAME = "Thomas" WHERE NAME = "Tom";
  • 만약 index를 사용하지 않은 컬럼을 조회해야 하는 상황이라면 전체를 탐색하는 Full Scan을 사용해야 한다. Full Scan은 전체를 비교하여 탐색하기 때문에 처리 속도가 떨어진다.
  • 사용되지 않는 인덱스는 바로 제거 하는 것이 좋다.

인덱스(index)의 장점과 단점

장점 단점
테이블을 조회하는 속도와 그에 따른 성능을 향상시킬 수 있다. 인덱스를 관리하기 위해 DB의 약 10%에 해당하는 저장공간이 필요하다.
전반적인 시스템의 부하를 줄일 수 있다. 인덱스를 관리하기 위해 추가 작업이 필요하다.
인덱스를 잘못 사용할 경우 오히려 성능이 저하되는 역효과가 발생할 수 있다.

인덱스(index)를 사용하면 좋은 경우

  1. 규모가 작지 않은 테이블
  2. INSERT, UPDATE, DELETE가 자주 발생하지 않는 컬럼
  3. JOIN이나 WHERE  또는 ORDER BY에 자주 사용되는 컬럼
  4. 데이터의 중복도가 낮은 컬럼

[인덱스의 자료구조] 5-2. B-트리

이진트리에서 발전되어 모든 리프노드들이 같은 레벨을 가질 수 있도록 자동으로 벨런스를 맞추는 트리

  • 인덱스는 보통 B-트리라는 자료구조로 이루어져 있다.
  • 정렬된 순서를 보장하고, 멀티레벨 인덱싱을 통한 빠른 검색을 할 수 있기 때문에 DB에서 사용하는 자료구조 중 한 종류
  • 루트 노드(1), 리프 노드(2), 그리고 루트 노드와 리프 노드 사이에 있는 브랜치 노드(3)로 나뉜다.

B-트리 탐색 과정

1. 루트 노드에서 탐색을 시작한다.
2. K를 찾았다면 탐색을 종료한다.
3. K와 노드의 key 값을 비교해 알맞은 자식 노드로 내려간다.
4. 해당 과정을 리프 노드에 도달할 때까지 반복한다.
5. 리프 노드에서도 K를 찾지 못한다면 트리에 값이 존재하지 않는 것이다.

B트리 예제

  1. 트리 탐색은 맨 위 루트 노드부터 탐색이 일어나고 브랜치 노드를 거쳐 리프 노드까지 내려온다.
  2. '57보다 같거나 클 때까지 <='를 기반으로 처음 루트 노드에서는 39, 83 이후 아래 노드로 내려와 46, 53, 57 등 정렬된 값을 기반으로 탐색하는 것을 볼 수 있다.
  3. 이렇게 루트 노드부터 시작해 마지막 리프 노드에 도달해서 57이 가리키는 데이터 포인트를 통해 결괏값을 반환하게 된다. 

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

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

대수확장성: 트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것

기본적으로 인덱스가 한 깊이씩 증가할 때마다 최대 인덱스 항목의 수는 4배씩 증가한다.

트리의 대수확장성

위의 표처럼 트리 깊이는 열 개짜리로, 100만 개의 레코드를 검색할 수 있다는 의미이다. 

참고로 실제 인덱스는 이것보다 훨씬 더 효율적이며, 그렇기 때문에 인덱스가 효율적이라고 볼 수 있다.

5-3. 인덱스 만드는 방법

인덱스를 만드는 방법은 데이터베이스마다 다르며 MySQL과 MongoDB를 기준으로 설명한다.

MySQL

MySQL의 경우 클러스터형 인덱스와 세컨더리 인덱스가 있고, 클러스터형 인덱스는 테이블 당 하나를 설정할 수 있다. 

 

클러스터형 인덱스(Clustered Index) 세컨더리 인덱스(Secondary Index)
primary key 옵션으로 기본키로 만들거나(1) unique not null 옵션을 붙이면(2) 클러스터형 인덱스로 만들 수 있다.  create index... 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있다.
테이블 당 하나만 가질 수 있다.  테이블 당 여러개 가질 수 있다.
하나의 인덱스만 생성한다면 클러스터형 인덱스를 만드는 것이 세컨더리 인덱스를 만드는 것보다 성능이 좋다. 보조 인덱스로 여러 개의 필드 값을 기반으로 쿼리를 많이 보낼 때 생성해야 하는 인덱스
ex) age라는 하나의 필드만으로 쿼리를 보낸다면 클러스터형 인덱스가 good! ex) age, name, email 등 다양한 필드를 기반으로 쿼리를 보낼때는 세컨더리 인덱스가 good!

Mongo DB 

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

5-4. 인덱스 최적화 기법

데이터베이스마다 조금씩 다르지만 기본적인 골조는 똑같기 때문에 특정 데이터베이스를 기준으로 설정해도 무방하다. 여기서는 MongoDB를 기반으로 인덱스 최적화 기법을 설명하고, 이를 기반으로 다른 데이터베이스에 웬만큼 적용할 수 있다. 

1. 인덱스는 비용이다.

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

2. 항상 테스팅하라.

  • 인덱스 최적화 기법은 서비스 특징에 따라 달라진다. 
  • 서비스에서 사용하는 객체의 깊이, 테이블의 양 등이 다르기 때문에 항상 테스팅하는 것이 중요하다.
  • explain( ) 함수를 통해 인덱스를 만들고 쿼리를 보낸 이후에 테스팅을 하며 걸리는 시간을 최소화해야한다.
EXPLAIN
SELECT * FROM t1
JOIN t2 ON t1.c1 = t2.c1

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

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

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

 

 

 

 

 

 

 

 

 


인덱스(index)란?

'이것이 MySQL이다'로 정리해보는 인덱스 개념

 

 

 

 

그림으로 알아보는 B-Tree