[정리] Mongoose Index 설정 이슈 및 기본세팅

2021. 2. 22. 15:02프로그래밍-Web/MongoDB

<Index 설정의 문제점>

 

무분별하게 다량의 데이터에 인덱싱을 하는 경우, CUD에 큰 문제가 생길 수 있다.

기본적으로 대부분의 인덱스는, 인덱싱된 데이터를 기준으로 Binary tree 탐색을 수행한다.

이로 인해 필요한 영역에 대해서만 데이터 스캔이 가능하다.

 

예컨데 다음과 같은 데이터가 있다고 해보자.

해당 데이터 중 '이름'에 인덱싱 처리를 하면 아래와 같은 테이블이 생길것이다.

만약 이름에 '송종국'이라는 데이터를 가지고 있는 Document에 대한 질의를 수행한다면

5번 도큐먼트만 메모리로 끌어올리는 Single block I/O가 일어난다

반면 '토트넘'으로 찾는다면, 여기에는 인덱싱 처리가 되어있지 않으므로 모든 Document를 끌어올려 질의를 수행하는 Multi block I/O가 일어난다

이렇게 적절한 인덱싱은 불필요한 full scan을 피할 수 있다.

 

 

문제는 CUD하는 경우이다.

예컨데 Insert 쿼리를 수행한다고 해보자. 

이 경우 index의 순서를 맞추기 위해서는 테이블을 재조합 하는 소모가 따른다

'고종수'라는 document를 Insert하면 5개의 도큐먼트는 순서가 하나씩 밀리고 고종수가 삽입된다

만약 index가 없었다면 고종수 document는 맨뒤에 그냥 들어갔을 것이다.

이를 index split 현상이라고 한다.

이는 삭제나 업데이트의 경우도 동일하다

특히 삭제의 경우는 인덱스가 삭제되지않고 '사용안함'으로 처리되므로, 정작 scan 할때에는 scan의 대상이 되어 속도가 느려지는 원인이된다.

 

 

<MongoDB 인덱스 세팅>

 

Mongoose를 활용한 인덱스는 보통 필드나 스키마에 대해 세팅된다.

예시로 보자면 tags에 index:true 옵션을 달아서 인덱싱하거나, 모델을 export할때 index메소드를 이용하여 컬럼을 지정한다

이때 1과 -1은 인덱스의 오름차순, 내림차순에 대한 설정이다.

기본적으로 MongoDB는 _id 에 대해 인덱싱처리를 수행해준다. 따라서 _id로 질의할때는 자동으로 index 처리 된 컬럼에 대해 질의하는 셈이 된다.

 

 

<MongoDB 인덱스 분류>

 

크게는 단일 인덱스(single)복합 인덱스(compound)로 구분된다.

 

단일 인덱스의 경우 하나의 특정컬럼을 기준으로 index를 붙이는 가장 흔한 경우이다. 

만약 두 개의 분류를 이용해 찾으려 한다면 복합인덱스가 필요하다.

위의 예시를 가져오자면, '수원'에 속해있는 '김'씨성의 선수를 찾는 경우다.

이런 경우에는 '소속'으로 먼저 인덱싱되어있는 도큐먼트에 대해 다시 '가나다'순으로 이름이 인덱싱되어있어야 한다.

이 경우 '소속'과 '이름'이라는 두개의 컬럼을 가지고 index를 만드는 경우이고 이를 복합인덱스 라고 한다.

이때 이름-소속순으로 index를 처리한다면 찾기가 더 어려워질 것이므로, 복합인덱스에서는 순서를 중요시한다. 

 

복합인덱스의 경우 인덱스 지정 컬럼 a,b의 조합인 엔트리로 구성되어 있다.

이때 index에 unique 옵션을 설정해주면 조합의 모든 구성 데이터가 중복될 수 없다

예시로 따져보면 수원 소속인 데이터가 하나 존재하는데 또 다른 수원 소속 데이터를 집어넣을 수 없다는 뜻이다.

 

dense(밀집) 와 sparse(희소) 인덱스로 구분하기도 한다.

 

기본적으로 index는 dense하도록 설정되어있다.

dense인덱스란 컬렉션 내의 한 도큐먼트가 인덱스 키가 없더라도, 인덱스에는 해당 엔트리가 존재한다는 것이다.

index 처리된 컬럼 데이터를 지정해주지 않으면 null 로 인덱스가 생성된다.

이렇게 null에 대한 인덱스가 존재하지 않는 index를 sparse 인덱스라고 한다

sparse 인덱스는 특정 컬럼이 required 요소가 아닌데 index를 지정한 경우에 보통 필요로한다

또한 null로 인덱스를 갖는 것 자체가 모두 쓸모없는 소모이므로 문제가 된다.

예컨데 위처럼 연봉이라는 컬럼이 있고, 이는 requried가 아닌데 index를 지정했다고 해보자.

이러한 경우 연봉이 없는 Document에 대해선 null index가 생기게 되고, 추후 null 값을 갖는 Document가 인서트될때 문제가 된다.

따라서 이러한 경우 sparse를 true로 해주면 된다.

 

이외에 배열의 embedded된 document들을 인덱싱하는 multiple index 등이 존재한다