MongoDB의 Index에 관하여...(2) Multikey Index

YB·2024년 3월 3일

DB 공부

목록 보기
5/6
post-thumbnail

MongoDB에서 Index의 종류

  • 인덱스가 걸리는 필드 개수에 따른 종류 (지난 글)
    - 단일 필드 인덱스
    - 복합 인덱스
  • 인덱스의 성격에 따른 분류
    - 다중 키 인덱스 (이번 글)
    - geospatial 인덱스
    - text 인덱스
    - 해쉬 인덱스

다중 키 인덱스(=Multikey Index)

  • 배열값이 포함된 필드에서 데이터를 수집하고 정렬 -> 배열 필드에 대한 쿼리 성능을 향상시킴
  • 배열값이 포함된 필드에 인덱스를 지정하면 MongoDB가 자동으로 해당 인덱스를 Multikey Index로 설정함
  • 다중 키 인덱스 생성 방법
    db.<collection>.createIndex( { <필드이름(배열)>: <정렬순서> } )
  • Index Bounds는 몽고 DB가 쿼리를 수행할 때 검색할 인덱스의 범위를 정의함

  • 복합 인덱스(Compound Index: 여러 키값을 갖는 index)에서, 각 인덱스는 배열값을 최대 1개까지만 포함할 수 있음

    { _id: 1, scores_spring: [ 8, 6 ], scores_fall: [ 5, 9 ] }
    { scores_spring: 1, scores_fall: 1 } 
    • 위 코드처럼 scores_spring 배열과 scores_fall이라는 배열을 필드로 갖는 컬렉션에서 저 둘을 모두 Index로 지정할 수 없음
    { _id: 1, scores_spring: [8, 6], scores_fall: 9 }
     { _id: 2, scores_spring: 6, scores_fall: [5, 7] }
    • 근데 이건 됨 (왜냐면 각 document에서 복합 다중 키에 의해 인덱싱 된 필드중 하나씩만 배열이니까)
    • 만약 하나의 Multikey Index를 이미 만들었다면, 이 컬렉션에 다른 배열을 갖는 필드를 삽Insert 할 수 없음. 하려고 하면 Insert 실패함
  • 배열 필드를 통으로 검색하는 쿼리에서는 MongoDB가 맨 앞의 element에 대해서만 index scan에 활용할 수 있고, 통으로 인덱스를 검색할수는 없음

    예시)
    데이터:

    db.inventory.insertMany( [
     { _id: 5, type: "food", item: "apple", ratings: [ 5, 8, 9 ] }
     { _id: 6, type: "food", item: "banana", ratings: [ 5, 9 ] }
     { _id: 7, type: "food", item: "chocolate", ratings: [ 9, 5, 8 ] }
     { _id: 8, type: "food", item: "fish", ratings: [ 9, 5 ] }
     { _id: 9, type: "food", item: "grapes", ratings: [ 5, 9, 5 ] }
     ] )

    인덱스:

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

    쿼리:

    db.inventory.find( { ratings: [ 5, 9 ] } )
    • 이 상태에서 위 쿼리는 [5,9]를 한번에 싹 인덱싱 된 상태에서 찾을수가 없음
    • 배열의 첫 번째 element인 5에대해서, ratings 배열에 5가 포함된 모든 document를 찾음
    • 그다음 결과 중에 ratings 배열이 [5,9]와 완전히 일치하는 document들을 찾아서 반환함
  • 다중 키 인덱스를 이용해서 정렬할 때 Blocking Sort가 발생함.

    • Blocking sort: 출력이 반환되기 전에 메모리에서 수행되어야 하는 정렬. 큰 Data set에서는 성능에 영향을 미칠 수 있음
    • Blocking sort를 발생시키지 않으려면 아래 두 조건을 만족해야 함(참고. 무슨 뜻인지 모르겠음)
      • 모든 정렬 필드들의 범위가 [MinKey, MaxKey]
      • 어떤 멀티 키 인덱스의 범위도 그 정렬 패턴과 같은 path prefix를 갖지 않음
  • Multikey Index들은 배열 필드에 대해서 query를 cover 할 수 없음.

    • covered query: 인덱스를 사용하여 완전히 만족할 수 있고 문서를 검사할 필요가 없는 쿼리
      • 쿼리에 있는 모든 필드가 Index의 일부이고
      • 결과로 나오는 모든 필드가 같은 인덱스에 있고
      • 쿼리 된 모든 필드가 null 이 아님
    • 근데 배열이 아닌 필드에 대해서는 query를 cover 할 수 있음
      db.matches.insertMany( [
       { name: "joe", event: ["open", "tournament"] },
       { name: "bill", event: ["match", "championship"] }
       ] )

      여기에서

      db.matches.createIndex( { name: 1, event: 1 } )

      이렇게 인덱스를 생성했을 때

      db.matches.find( { name: "bill" } )

      이렇게 name 필드에 대한 쿼리는 Cover할 수 있음
      -> name 필드가 이 인덱스의 index prefix이니까
      근데 name이랑 event 둘다 쿼리에 포함된 경우 Cover할 수가 없음

  • 다중 키 인덱스를 Shard key Index로 지정할 수 없고, Hashed Index는 다중 키 인덱스일 수 없음.
    • Shard key Index / Hashed Index가 뭔지 모름: 나중에 알게 되겠지
  • $expr 연산자를 사용할 수 없음 : $expr도 모름

참고:

profile
뭐라도 만들어본다

0개의 댓글