■ MongoDB

[MongoDB] 몽고디비 인덱싱에 대하여..

인덱싱은 개념은 쉽지만 막상 대규모에 적용하려면 상당히 까다로운 문제에 직면하게 된다.

그중 몽고디비에서 아주 사소하지만 반드시 알아둘 것들을 정리해 보았다.

1. 몽고디비에서 부정(negation)에 대한 쿼리는 되도록 사용하지 말자.

부정에 대한 쿼리는 일반적으로 잘 작동하지 못할 수 있다. 작동을 잘 못한단 의미는 잘할수도 있고 아닐수도 있다는 의미다.

좀 더 깊이 가보자. 예를 들면

{
  nick: {
    $ne: /^hwa/
  }
}

다음과 같은 쿼리가 있다고 했을경우,  hwa로 시작되지 않는 문자열을 위해 모든 쿼리를 검색한다.

이는 hwa로 시작되는 문자열을 찾는 것과는 다르게 매우 비효율 적이다.

세세한거 따지기 싫다면 왠만하면 부정은 쿼리에 사용하지 말자. (부정의 반대는 긍정이므로 반드시 대칭되는 쿼리가 있을것이다.)

 

2. 위에서 /^hwa/ 라는 쿼리를 썼다. 정규식은 일반적으로 인덱싱이 되지 않는다. 하지만 접두어(prefix)의 경우 인덱싱이 가능하다.

 

3.  복합인덱스 순서에서 범위필드에 인덱싱은 항상 마지막으로 작성한다. 범위필드는 마지막에 해당하는 모든 쿼리를 찾고 최종적으로 제한하는 역할을 한다.

 

4. 몽고디비에서는 하나의 쿼리당 하나의 인덱스만을 사용할 수 있다. 하지만 OR쿼리는 $or: [] 안에 있는 배열의 개수만큼 인덱스를 이용하여 쿼리를 수행한다. 당연한 말이겠지만 여러개의 검색된 n개의 도큐먼트 집합이 있다는 의미이며, 몽고디비는 이 도큐먼트 집합들을 합치는데 또다른 비용을 소모한다. 가능하면 $in으로 가자.

 

5. 다음과 같은 내장된 도큐먼트에 대한 인덱스를 수행할 경우,

ensureIndex({'user.nick': 1});

반드시 쿼리문 작성 또한

find({'user.nick': 'hwarang'})

위 처럼 되야한다. 만약

find({user:{nick:'hwarang'}})

다음과 같다면 인덱스는 user에 대한 인덱스를 수행할 것이다.

 

6. 배열에 대한 인덱스는 다중키 인덱스라고 하는데, 이는 배열의 모든 요소에 인덱싱을 하는 것이다. 따라서 대체로 일반 인덱스보다 비용이 많이 든다. 또한 두개이상의 배열을 한번에 인덱싱 할수 없다. 예를들면

ensureIndex({friends: 1, family: 1});
find({friends:['1', '2'], family:['0', '1']};

다음과 같은 상황에서 friends와 family 두개의 키로 인덱스를 생성했는데 두개 모두 배열이다. 즉 두개이상의 배열을 한번에 인덱싱할 수없다는 원칙에 의거하여 에러가 날 것이다. 왜 안되는지에 대한 이유는, 다중키 인덱스는 각 요소마다 인덱싱을 한다고 했는데 2개의 배열은 n*m개 3개의 배열은 n*m*s개의 인덱스가 생성될 것이기 때문이다. (이는 심하게 비용낭비이다.)

 

7.  인덱싱할 필드는 카디널리티가 낮은것을 선택하자.  이유는 높은 카디널리티를 갖고 있는 필드는 인덱싱의 위력을 발휘하지 못한다. 낮은 카디널리티일수록 인덱싱의 진가가 발휘된다. (카디널리티는 한 필드의 중복성의 정도를 나타낸다. 만약 필드가 enum타입을 갖고 있다면 낮은 카디널리티가 된다. 가장 높은 카디널리티는 unique key (pk)가 된다.)

Standard

댓글 남기기