문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / /

멀티키 인덱스 바운드

이 페이지의 내용

  • 멀티키 인덱스의 경계 교차점
  • 예제: 경계 교차
  • $elemMatch가 없는 쿼리
  • 멀티키 인덱스의 복합 바운드
  • 예제: 비배열 필드와 배열 필드의 복합 경계
  • 예제: 비배열 필드와 다중 배열 필드의 복합 경계
  • 동일한 배열에서 여러 필드의 복합 경계
  • 예시: 발산되는 필드 경로의 $elemMatch

인덱스 바운드 는 MongoDB가 인덱스를 사용하여 쿼리를 수행할 때 검색하는 인덱스 값의 범위를 정의합니다. 인덱싱된 필드에 여러 쿼리 조건자를 지정하는 경우, MongoDB는 해당 조건자의 경계를 결합하여 경계가 더 작은 인덱스 스캔을 생성하려고 시도합니다. 인덱스 바운드가 작을수록 쿼리 속도가 빨라지고 리소스 사용량이 줄어듭니다.

MongoDB는 교차 또는 복합 경계로 경계를 결합합니다.

경계 교차점은 여러 경계가 겹치는 점을 나타냅니다. 예를 들어, [ [ 3, Infinity ] ][ [ -Infinity, 6 ] ] 경계가 주어지면 경계의 교집합은 [ [ 3, 6 ] ] 가 됩니다.

인덱싱된 배열 필드가 주어지면 배열에 여러 쿼리 술어를 지정하고 멀티키 인덱스 를 사용하여 쿼리를 수행하는 쿼리를 가정해 보겠습니다. MongoDB는 $elemMatch 연산자가 쿼리 술어를 조인하는 경우 다중 키 인덱스 경계를 교차할 수 있습니다.

다음 예제는 MongoDB가 바운드 교차를 사용하여 쿼리할 값의 범위를 더 좁혀 쿼리 성능을 개선하는 방법을 보여줍니다.

1

필드가 name 이고 배열 필드가 grades 인 문서가 포함된 students collection을 생성합니다.

db.students.insertMany(
[
{ _id: 1, name: "Shawn", grades: [ 70, 85 ] },
{ _id: 2, item: "Elena", grades: [ 92, 84 ] }
]
)
2

grades 배열에 멀티키 인덱스 를 생성합니다.

db.students.createIndex( { grades: 1 } )
3

다음 쿼리를 실행합니다.

db.students.find( { grades : { $elemMatch: { $gte: 90, $lte: 99 } } } )

앞의 쿼리는 $elemMatch 을 사용하여 grades 배열에 지정된 조건과 두 조건 모두 와 일치하는 요소가 하나 이상 포함된 문서를 반환합니다.

쿼리 술어를 별도로 사용합니다.

  • 90보다 크거나 같은 조건자($gte: 90)의 경계는 [ [ 90, Infinity ] ] 입니다.

  • 99보다 작거나 같은 조건자($lte: 99)의 경계는 [ [ -Infinity, 99 ] ] 입니다.

쿼리가 $elemMatch 을 사용하여 이러한 술어를 조인하기 때문에 MongoDB는 다음과 경계를 교차합니다.

ratings: [ [ 90, 99 ] ]

쿼리가 배열 필드의 조건에 $elemMatch 조인하지 않으면 MongoDB는 멀티키 인덱스 경계를 교차할 수 없습니다.

다음 쿼리를 고려해보세요.

db.students.find( { grades: { $gte: 90, $lte: 99 } } )

쿼리는 grades 배열에서 다음을 검색합니다.

  • ~보다 크거나 같은 요소가 하나 이상 90

  • ~보다 작거나 같은 요소가 하나 이상 있습니다. 99

동일한 요소가 두 기준을 모두 충족할 수 있습니다.

앞의 쿼리는 $elemMatch 을(를) 사용하지 않기 때문에 MongoDB가 경계를 교차하지 않습니다. 대신 MongoDB는 다음 바운드 중 하나를 사용합니다.

  • [ [ 90, Infinity ] ]

  • [ [ -Infinity, 99 ] ]

MongoDB는 두 가지 경계 중 무엇을 선택할지 보장하지 않습니다.

복합 바운드는 복합 인덱스 의 여러 키에 대한 바운드를 결합합니다. 여러 키의 바운드를 사용하면 MongoDB가 각 바운드에 대한 결과를 개별적으로 계산할 필요가 없기 때문에 쿼리를 처리하는 데 걸리는 시간이 줄어듭니다.

예를 들어 다음과 같은 경계를 가진 복합 인덱스 { temperature: 1, humidity: 1 } 을 생각해 보겠습니다.

  • temperature 의 경계는 [ [ 80, Infinity ] ] 입니다.

  • humidity 의 경계는 [ [ -Infinity, 20 ] ] 입니다.

경계를 복합하면 두 경계가 모두 사용됩니다.

{ temperature: [ [ 80, Infinity ] ], humidity: [ [ -Infinity, 20 ] ] }

MongoDB가 두 경계를 복합할 수 없는 경우 MongoDB는 선행 필드의 경계만큼 인덱스 스캔을 제한합니다. 이 예제에서 선행 필드는 temperature 이므로 제약 조건이 temperature: [ [ 80, Infinity ] ] 발생합니다.

다음 예제는 MongoDB가 복합 경계를 사용하여 보다 효율적인 쿼리 제약 조건을 정의하여 쿼리 성능을 개선하는 방법을 보여줍니다.

1

필드가 item 이고 배열 필드가 ratings 인 문서가 포함된 survey collection을 생성합니다.

db.survey.insertMany(
[
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] },
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
]
)
2

itemratings 필드에 복합 멀티키 인덱스 를 생성합니다.

db.survey.createIndex( { item: 1, ratings: 1 } )
3

다음 쿼리를 실행합니다.

db.survey.find( { item: "XYZ", ratings: { $gte: 3 } } )

앞의 쿼리는 인덱스(itemratings)의 두 키 모두에 조건을 지정합니다.

술어를 별도로 사용합니다.

  • item: "XYZ" 술어의 경계는 [ [ "XYZ", "XYZ" ]] 입니다.

  • ratings: { $gte: 3 } 술어의 경계는 [ [ 3, Infinity ] ] 입니다.

MongoDB는 다음과 같은 결합된 범위를 사용합니다.

{ item: [ [ "XYZ", "XYZ" ] ], ratings: [ [ 3, Infinity ] ] }

다음 예제는 인덱스에 배열이 아닌 필드와 여러 개의 배열 필드가 포함된 경우 MongoDB가 복합 경계를 사용하는 방법을 보여줍니다.

1

문자열 필드 item 및 배열 필드 ratings 가 있는 문서가 포함된 survey2 collection을 생성합니다.

db.survey2.insertMany( [
{
_id: 1,
item: "ABC",
ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]
},
{
_id: 2,
item: "XYZ",
ratings: [ { score: 5, by: "anon" }, { score: 7, by: "wv" } ]
}
] )
2

다음 필드에 복합 인덱스를 생성합니다.

  • item (비배열)

  • ratings.score (배열)

  • ratings.by (배열)

db.survey2.createIndex(
{
"item": 1,
"ratings.score": 1,
"ratings.by": 1
}
)
3

다음 쿼리를 실행합니다.

db.survey2.find(
{
item: "XYZ",
"ratings.score": { $lte: 5 },
"ratings.by": "anon"
}
)

술어를 별도로 사용합니다.

  • item: "XYZ" 술어의 경계는 [ [ "XYZ", "XYZ" ] ] 입니다.

  • score: { $lte: 5 } 술어의 경계는 [ [ -Infinity, 5] ] 입니다.

  • by: "anon" 술어의 경계는 [ "anon", "anon" ] 입니다.

MongoDB는 쿼리 조건자와 인덱스 키 값에 따라 item 키의 경계를 "ratings.score" 또는 "ratings.by" 의 경계와 결합합니다. MongoDB는 item 필드와 어떤 경계를 결합하는지 보장하지 않습니다.

MongoDB는 다음 중 한 가지 방법으로 쿼리를 처리합니다.

  • MongoDB는 item 경계와 "ratings.score" 경계를 합성합니다.

    {
    "item" : [ [ "XYZ", "XYZ" ] ],
    "ratings.score" : [ [ -Infinity, 5 ] ],
    "ratings.by" : [ [ MinKey, MaxKey ] ]
    }
  • MongoDB는 item 경계와 "ratings.by" 경계를 합성합니다.

    {
    "item" : [ [ "XYZ", "XYZ" ] ],
    "ratings.score" : [ [ MinKey, MaxKey ] ],
    "ratings.by" : [ [ "anon", "anon" ] ]
    }

"ratings.score" 의 경계와 "ratings.by" 의 경계를 복합하려면 쿼리에서 $elemMatch 를 사용해야 합니다.

동일한 배열의 인덱스 키에 대한 경계를 복합하려면 다음 두 가지가 모두 충족되어야 합니다.

  • 인덱스 키는 필드 이름을 제외하고 동일한 필드 경로를 공유해야 합니다.

  • 쿼리는 해당 경로에서 $elemMatch 을(를) 사용하여 필드에 조건자를 지정해야 합니다.

내장된 문서의 필드에서 점으로 구분된 필드 이름(예: "a.b.c.d")은 d 의 필드 경로입니다. 동일한 배열의 인덱스 키에 대한 경계를 복합하려면 $elemMatch 가 필드 이름 자체를 제외한 최대 경로에 있어야 합니다(즉, "a.b.c").

다음 예시는 MongoDB가 동일한 배열의 인덱스 키에 대한 바운드를 결합하는 방법을 보여 줍니다. 이 예시에서는 이전 예시에서 사용된 survey2 컬렉션을 사용합니다.

1

ratings.scoreratings.by 필드에 복합 인덱스를 생성합니다.

db.survey2.createIndex( { "ratings.score": 1, "ratings.by": 1 } )

"ratings.score""ratings.by" 필드는 필드 경로 ratings 를 공유합니다.

2

다음 쿼리를 실행합니다.

db.survey2.find( { ratings: { $elemMatch: { score: { $lte: 5 }, by: "anon" } } } )

앞의 쿼리는 ratings 필드에 $elemMatch 를 사용하여 배열에 두 조건과 일치하는 단일 요소가 하나 이상 포함되도록 요구합니다.

술어를 별도로 사용합니다.

  • score: { $lte: 5 } 술어의 경계는 [ [ -Infinity, 5 ] ] 입니다.

  • by: "anon" 술어의 경계는 [ [ "anon", "anon" ] ] 입니다.

MongoDB는 두 바운드를 다음 바운드로 합성합니다.

{ "ratings.score" : [ [ -Infinity, 5 ] ], "ratings.by" : [ [ "anon", "anon" ] ] }

쿼리가 공통 경로에서 벗어나는 필드에 $elemMatch 를 지정하는 경우, MongoDB는 동일한 배열에 있는 인덱스 키의 경계를 복합 할 수 없습니다 .

다음 예에서는 분기하는 필드 경로의 $elemMatch 를 보여줍니다.

1

collection survey3 에 문자열 필드 item 와 배열 필드 ratings 가 있는 문서가 포함되어 있습니다.

db.survey3.insertMany( [
{
_id: 1,
item: "ABC",
ratings: [
{ scores: [ { q1: 2, q2: 4 }, { q1: 3, q2: 8 } ], loc: "A" },
{ scores: [ { q1: 2, q2: 5 } ], loc: "B" }
]
},
{
_id: 2,
item: "XYZ",
ratings: [
{ scores: [ { q1: 7 }, { q1: 2, q2: 8 } ], loc: "B" }
]
}
] )
2

ratings.scores.q1ratings.scores.q2 필드에 복합 인덱스를 생성합니다.

db.survey3.createIndex( { "ratings.scores.q1": 1, "ratings.scores.q2": 1 } )

"ratings.scores.q1""ratings.scores.q2" 필드는 필드 경로 "ratings.scores" 를 공유합니다. 인덱스 경계를 복합화하려면 쿼리에서 공통 필드 경로에서 $elemMatch 을(를) 사용해야 합니다.

3

다음 쿼리는 필수 경로에 없는 $elemMatch 을(를) 사용합니다.

db.survey3.find( { ratings: { $elemMatch: { 'scores.q1': 2, 'scores.q2': 8 } } } )

MongoDB는 인덱스 경계를 복합할 수 없으며 인덱스 스캔 중에 "ratings.scores.q2" 필드는 제약이 없습니다.

경계를 복합하려면 쿼리에서 공통 경로 "ratings.scores" 에서 $elemMatch 을(를) 사용해야 합니다.

db.survey3.find( { 'ratings.scores': { $elemMatch: { 'q1': 2, 'q2': 8 } } } )
← 배열의 포함된 필드에 인덱스 만들기