공대생 정리노트

mongoDB - 배열 인덱싱 본문

로드맵/DB

mongoDB - 배열 인덱싱

woojinger 2022. 1. 25. 23:37

Reference

https://docs.mongodb.com/manual/core/index-multikey/

 

Multikey Indexes — MongoDB Manual

Docs Home → MongoDB ManualTo index a field that holds an array value, MongoDB creates an index key for each element in the array. These multikey indexes support efficient queries against array fields. Multikey indexes can be constructed over arrays that

docs.mongodb.com

https://docs.mongodb.com/manual/tutorial/query-arrays/#std-label-array-match-exact

 

Query an Array — MongoDB Manual

Docs Home → MongoDB Manual➤ Use the Select your language drop-down menu in the upper-right to set the language of the following examples.The following example queries for all documents where the field tags value is an array with exactly two elements, "

docs.mongodb.com

http://www.yes24.com/Product/Goods/97980005

 

몽고DB 완벽 가이드 - YES24

NoSQL의 진수 몽고DB 개발부터 관리까지몽고DB 입문자를 위한 기초부터 실제 배포에 적용할 수 있는 실용적이고 깊이 있는 내용까지 담았다. 개정 3판에서는 성능이 강화된 몽고DB 최신 버전을 반

www.yes24.com


mongoDB 스키마를 짤 때 고민이 되는 지점이 있었다.

두 개의 필드를 이용해서 검색을 해야 하는 상황이라고 생각해 보자.

두 개의 필드를 따로 분리해서 인덱싱하는 것과 배열에 넣어서 인덱싱하는 것이 큰 차이가 있을까?  

예를 들어

{ _id: 1, key1: "value1", key2: "value2" }

이런 형식을 가진 컬렉션과

{ _id: 1, key: [ "value1","value2" ] }

이렇게 배열로 값들을 가지고 있는 컬렉션에 대해서

"value1"과 "value2"를 가지고 있는 문서를 find할 때 속도가 차이가 있는지 궁금했다.

 

만약 큰 차이가 없다면 아래의 경우 필드를 추가할 때 확장하기가 용이하고(위 컬렉션의 경우 key3 필드를 추가로 만들어야 한다), 클라이언트가 쿼리를 날리기에도 깔끔하다.

 

그래서 위 두 경우를 비교해보기로 하였다.

 

이론

https://docs.mongodb.com/manual/core/index-multikey/

배열 필드 인덱싱은 배열 자체가 아니라 배열의 각 요소를 인덱싱한다

위 그림을 보면 조금 더 쉽게 이해를 할 수 있다.

 

배열에 대해 정확한 match를 위한 쿼리를 수행할 때, mongoDB는 다중키 인덱스를 query array의 첫번째 원소에 대해서는 사용하지만 전체 배열을 찾기 위해서는 사용할 수 없다.

대신 배열의 첫번째 원소를 찾기 위해 다중키 인덱스를 사용한 후에 쿼리의 배열과 매치되는 문서를 찾는다.

 

이게 무슨말인지 다음 예를 따라가 보자.

{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] }
{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] }
{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] }
{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] }
{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }

위와 같은 5개의 문서가 존재하는 상황이다.

 

이때 다음과 같이 인덱스를 만들었다고 하자.

db.inventory.createIndex( { ratings: 1 } )

자 이 상황에서 다음의 쿼리를 날려보자.

db.inventory.find( { ratings: [ 5, 9 ] } )

그러면 mongoDB는 다중키 인덱스로 ratings 배열에 5가 있는 문서를 먼저 찾는다. 즉, 쿼리의 첫번째 원소만 인덱스를 쓰는데 사용한다.

그 다음 얻은 문서들 중 [5, 9]와 일치하는 것을 필터링한다.

 

즉, 두 번째 원소부터는 Indexing이 큰 효력을 발휘하지 못한다고 예상할 수 있다.

 

실험 조건

실험 조건은 다음과 같다.

// collection1
{ _id: 1, key1: "value1", key2: "value2" }
// collection2
{ _id: 1, key: [ "value1", "value2"] }
  • 검색 대생 총 문서는 600만 개
  • "value1"을 가지고 있는 문서 검색 실험 1번
  • "value1", "value2"을 가지고 있는 문서 검색 실험 2번
  • collection1은 key1에 인덱스 한 개, key1, key2에 다중키 인덱스 한 개. 총 두 개의 인덱스를 만든다.
  • colleciton2는 key에 인덱스 한 개를 만든다.

 

실험 결과

"value1" 검색 (필드 한 개 검색) - 검색 결과 문서 170만개

collection1 : 0.033s

collection2 : 0.16s

 

"value1", "value2" 검색 (필드 두 개 검색) - 검색 결과 문서 56만개

collection1 : 0.016s

collection2 : 0.06s

 

예상했던 대로 필드를 분리해서 인덱싱을 거는 것이 성능이 뛰어나다.(4~5배)

이정도 성능이면 크지 않은 규모의 어플리케이션에서는 배열을 인덱스로 사용해도 크게 차이가 나지 않을 것 같긴 하다

'로드맵 > DB' 카테고리의 다른 글

Recovery System(1)  (0) 2022.03.19
mongdoDB 내부 캐시  (1) 2022.01.27
SQL VS NoSQL  (0) 2020.08.30
Comments