Backend/Database

인덱스를 걸면 왜 빠른지 비유로 이해하기

mopil 2023. 12. 29. 02:41
반응형

데이터베이스의 조회 성능을 끌어올리기 위해서 가장 우선적으로 검토되는 것이 "인덱스"다.

 

칼럼에 인덱스를 설정하면 왜 조회 성능이 빨라지는지 비유적으로 이해해 보자.

 

 

# 책의 목차 비유

1000장이 넘는 데이터베이스 책이 있다고 가정하자. 책의 구성은 트랜잭션, 인덱스, 샤딩, 파티셔닝 등 다양하다.

 

이때, 우리는 인덱스 관련 부분만 읽고 싶다.

 

이럴 때 우리는 목차를 찾아가서 인덱스 관련 부분이 몇 페이지에 존재하는지 확인 후 곧바로 해당 페이지로 이동한다.

 

목차를 보니, 320페이지부터 인덱스 관련 내용이 시작이다.

 

이를 바탕으로 처음부터가 아니라 320페이지부터만 훑어보면 된다.

 

만약 목차가 없다면 어떻게 할까? 처음부터 하나씩 페이지를 훑어보면서 인덱스 관련 주제가 나오는지 찾아봐야 할 것이다.

 

 

이 목차라는 표가 디비 관점에서 인덱스이다.

(인덱스를 번역하면 목차라는 뜻이기도 하다)

 

320번째 페이지에 우리가 원하는 정보가 있음을 알았다. 이제 우리는 해당 페이지로 찾아가기만 하면 된다.

 

우리는 대충 총 1000장이니까, 1/3 지점을 어림잡아 펼치고 그때부터 320페이지를 찾을 것이다.

 

# 원하는 정보를 빨리 찾는 원리

만약 책 페이지가 1부터 순차적으로 증가하는 게 아니라 뒤죽박죽이라면? 어림잡아 펼치는 걸 할 수 없다.

 

즉, 특정 정보가 어디에 존재하는지를 알아도 정보 자체가 정렬되어 있지 않으면 위치 정보(320페이지)가 의미 없음을 알 수 있다.

 

다행히 모든 책의 페이지는 1부터 순차적으로 증가하기 때문에 책의 페이지는 자동으로 정렬되어 있다.

 

페이지가 뒤죽박죽인 (페이지 기준 정렬이 안되어 있는) 책은 존재하지 않으므로 우리는 목차를 활용하기 위해선 '페이지가 정렬되어 있어야 하는구나'라는 인식이 없었을 수도 있다.

 

 

여기서 우리는 많은 데이터에서 특정 정보를 찾기 위해선 두 가지 조건이 필요함을 알 수 있다.

 

1. 원하는 정보가 어디에 존재하는지 알아야 함 (목차)

2. 그 정보의 기준이 정렬되어 있어야 함 (페이지)

 

# 디비 관점으로

책의 저자가 목차를 만들었듯, 디비도 정보를 찾을 수 있게 도와주는 목차를 만들어야 한다.

 

디비는 자신만의 목차를 1,2 조건을 모두 만족되도록 만드는데,

 

인덱스를 거는 칼럼을 정렬시켜서 어디에 존재하는지 정보를 저장하는 별도의 표를 만든다. (이 표가 B+Tree다)

 

그리고 이 표 디비에게 만들라고 지시하는 것이, 우리는 인덱스를 만든다고(혹은 건다라고) 표현한다.

 

PK는 인덱스가 기본으로 설정되는 이유

PK는 보통 레코드를 식별하는 값으로, 1씩 증가하는 형태를 가진다.

 

이는 책의 페이지 메커니즘과 동일하다.

 

즉, 순차 증가는 그 자체만으로 이미 정렬되어있기 때문에, 별도의 정렬 표를 만들지 않고도 인덱스 표로 사용될 수 있다.

 

 

정보 찾기 과정

그리고 앞서 우리가 "인덱스 관련 주제"를 목차로 빠르게 찾았던 것처럼, 데이터베이스도 동일한 조회 프로세스를 거친다.

 

우리

1. 인덱스 장이 어디 있는지 목차부터 찾아본다.

2. 목차에서 몇 페이지부터 인덱스 장이 존재하는지 파악한다. (320페이지)

3. 어림잡아 1/3 지점을 펼치고 그때부터 찾는다.

만약 목차가 없으면? 처음부터 순차적으로 탐색한다.

 

 

데이터베이스

1. 인덱스가 걸려있는 칼럼은 인덱스 표를 먼저 찾아본다.

2. 인덱스 표에서 어느 데이터가 어디에 존재하는지 파악한다.

3. 해당 주소를 찾아간다.

만약 인덱스가 없으면? 처음부터 순차적으로 탐색한다.

 

즉, 우리가 목차에서 바로 원하는 정보를 찾았듯이 인덱스를 걸면 순차적으로 탐색할 필요가 없어지므로 조회 속도가 빨라짐을 알 수 있다.

 

 

우리는 어림잡아서 탐색 위치를 찾았지만, 디비는 이진탐색 (정확히는 조금 다른) 방법을 통해 인덱스 표에서 원하는 정보의 위치를 빠르게 찾아간다.

 

책의 목차는 정렬 기준 데이터가 페이지로 고정이지만, 데이터베이스는 기준 데이터를 테이블의 모든 칼럼으로 좀 더 일반화한 것이라고 생각할 수 있다.

 

# 인덱스는 read 성능 up, write 성능 down 이유

인덱스를 만든다는 것은, 해당 칼럼에 대한 정렬된 표를 하나 만든다는 것이다.

 

즉, 정렬된 표를 만드는 행위가 추가되었다.

 

이는 메인테이블에 변경이 일어났을 때, 인덱스 표도 반영해 줘야 함을 의미한다.

 

관리포인트가 늘어났기 때문에, write 연산이 인덱스 표를 관리하지 않을 때 보다 좀 더 비용이 들어간다.

 

 

# 비슷한 내용이 많으면 무용지물

인덱스를 건 칼럼을 조회한다 해도 효과를 보기 힘든 경우가 있다.

 

바로 중복이 많은 칼럼을 인덱스로 설정했을 때이다.

 

예를 들어보자.

 

유저 테이블에 인덱스를 created_at 칼럼에 걸어놔서 생성일을 쭉 정렬해 놓은 인덱스 표가 생성되었다.

 

전체 데이터가 100만 건인데, 생성일이 1998-11-02 인건이 100만 건이라고 해보자.

 

그리고 우리는 1998-11-02에 생성된 데이터 중, 직업이 개발자인 데이터를 찾고 싶다.

 

그러면 디비는 인덱스를 봐서, 1998-11-02의 탐색 위치를 찾았지만, 100만 건의 데이터를 읽으면서 직업=개발자인 데이터를 찾게 될 것이다.

 

이러면 인덱스를 참조해서 읽나, 처음부터 순차적으로 읽나 동일한 상황이 발생한다.

 

이를 좀 더 개발적으로  해당 생성일 칼럼은 카디널리티가 낮다고 표현한다. (데이터의 중복도가 높다)

 

따라서 비슷한 내용이 많은 칼럼은 인덱스를 생성할 때 활용이 못 될 수 있음을 고려해야 한다.

 

좀 더 개발적으로

중복이 많은 경우 말고도,

 

is null / is not null 조건이나 like %문자열%, 복합 인덱스의 경우 인덱스 생성 순서와 다른 where 조건절인 경우도 인덱스를 타지 않으므로 기억하면 좋다.

 

 

# 정리

특정 칼럼을 정렬한 표를 만들어 전체 탐색 하기 전 이 표를 먼저 참조해 위치를 빠르게 찾는 것이 인덱스의 메인 원리임을 기억하자.

 

 

반응형