공대생 정리노트
mongoDB - 배열 인덱싱 본문
Reference
https://docs.mongodb.com/manual/core/index-multikey/
https://docs.mongodb.com/manual/tutorial/query-arrays/#std-label-array-match-exact
http://www.yes24.com/Product/Goods/97980005
mongoDB 스키마를 짤 때 고민이 되는 지점이 있었다.
두 개의 필드를 이용해서 검색을 해야 하는 상황이라고 생각해 보자.
두 개의 필드를 따로 분리해서 인덱싱하는 것과 배열에 넣어서 인덱싱하는 것이 큰 차이가 있을까?
예를 들어
{ _id: 1, key1: "value1", key2: "value2" }
이런 형식을 가진 컬렉션과
{ _id: 1, key: [ "value1","value2" ] }
이렇게 배열로 값들을 가지고 있는 컬렉션에 대해서
"value1"과 "value2"를 가지고 있는 문서를 find할 때 속도가 차이가 있는지 궁금했다.
만약 큰 차이가 없다면 아래의 경우 필드를 추가할 때 확장하기가 용이하고(위 컬렉션의 경우 key3 필드를 추가로 만들어야 한다), 클라이언트가 쿼리를 날리기에도 깔끔하다.
그래서 위 두 경우를 비교해보기로 하였다.
이론
배열 필드 인덱싱은 배열 자체가 아니라 배열의 각 요소를 인덱싱한다
위 그림을 보면 조금 더 쉽게 이해를 할 수 있다.
배열에 대해 정확한 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 |