Docs Menu
Docs Home
/
MongoDB 매뉴얼
/ /

멀티키 인덱스 바운드

이 페이지의 내용

  • 멀티키 인덱스의 경계 교차
  • 멀티키 인덱스의 복합 바운드

인덱스 스캔의 바운드는 쿼리 중에 검색할 인덱스 부분을 정의합니다. 인덱스에 대한 조건자가 여러 개 있는 경우, MongoDB는 더 작은 경계의 스캔을 생성하기 위해 교집합 또는 복합 을 통해 이러한 조건자의 경계를 결합하려고 시도합니다.

경계 교차는 논리적 접속사를 나타냅니다(예: AND)의 여러 경계입니다. 인스턴스, 두 개의 경계 [ [ 3, Infinity ] ][ [ -Infinity, 6 ] ] 이 주어졌을 때, 경계의 교차점은 [ [ 3, 6 ] ] 가 됩니다.

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

예를 들어, item 필드와 ratings 배열 필드가 있는 문서가 포함된 survey collection을 만듭니다.

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

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

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

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

db.survey.find( { ratings : { $elemMatch: { $gte: 3, $lte: 6 } } } )

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

  • 3 이상의 조건자에 대한 경계(즉, $gte: 3)은 [ [ 3, Infinity ] ] 입니다.

  • 6보다 작거나 같은 술어의 바운드(즉, $lte: 6)는 [ [ -Infinity, 6 ] ] 입니다.

쿼리가 $elemMatch 을(를) 사용하여 이러한 술어를 조인하기 때문에 MongoDB는 다음에 대해 경계를 교차할 수 있습니다.

ratings: [ [ 3, 6 ] ]

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

db.survey.find( { ratings : { $gte: 3, $lte: 6 } } )

쿼리는 ratings 배열에서 3보다 크거나 같은 요소와 6보다 작거나 같은 요소를 하나 이상 검색합니다. 단일 요소가 두 기준을 모두 충족할 필요는 없으므로 MongoDB는 경계를 교차하지 않고 [ [ 3, Infinity ] ] 또는 [ [ -Infinity, 6 ] ] 을 사용합니다. MongoDB는 이 두 가지 경계 중 무엇을 선택할지 보장하지 않습니다.

복합 바운드는 복합 인덱스 의 여러 키에 바운드를 사용하는 것을 말합니다. 예를 들어 a 필드의 경계가 [ [ 3, Infinity ] ] 이고 필드 b 의 경계가 [ [ -Infinity, 6 ] ] 인 복합 인덱스 { a: 1, b: 1 } 가 주어진 경우, 경계를 복합하면 두 경계를 모두 사용하게 됩니다.

{ a: [ [ 3, Infinity ] ], b: [ [ -Infinity, 6 ] ] }

MongoDB가 두 경계를 복합할 수 없는 경우 MongoDB는 항상 선행 필드(이 경우 a: [ [ 3, Infinity ] ])의 경계만큼 인덱스 스캔을 제한합니다.

복합 멀티키 인덱스를 고려하세요. 즉, 인덱싱된 필드 중 하나가 배열인 복합 인덱스 입니다. 예를 들어, item 필드와 ratings 배열 필드가 있는 문서가 포함된 survey collection을 만듭니다.

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

item 필드와 ratings 필드에 복합 인덱스 를 생성합니다.

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

다음 쿼리는 인덱스의 두 키에 대한 조건을 지정합니다.

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

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

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

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

MongoDB는 두 가지 경계를 복합하여 다음의 결합된 경계를 사용할 수 있습니다.

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

WiredTiger 및 인메모리 스토리지 엔진에만 해당됩니다.

멀티키 인덱스에서 MongoDB는 어떤 인덱싱된 필드 또는 여러 필드가 인덱스를 멀티키 인덱스로 만드는지 추적합니다. 이 정보를 추적하면 MongoDB 쿼리 엔진이 더 엄격한 인덱스 경계를 사용할 수 있습니다.

앞서 언급한 복합 인덱스 는 스칼라 필드 [1] item 와 배열 필드 ratings 에 있습니다.

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

WiredTiger 및 인메모리 스토리지 엔진의 경우, 쿼리 작업이 복합 멀티키 인덱스의 인덱싱된 스칼라 필드에 여러 조건자를 지정하는 경우, MongoDB는 필드의 경계와 교차합니다.

예를 들어, 다음 작업은 스칼라 필드에 대한 범위 쿼리와 배열 필드에 대한 범위 쿼리를 지정합니다.

db.survey.find( {
item: { $gte: "L", $lte: "Z"}, ratings : { $elemMatch: { $gte: 3, $lte: 6 } }
} )

MongoDB는 item ~ [ [ "L", "Z" ] ] 및 등급의 경계를 교차하여 [[3.0, 6.0]] 의 결합된 경계를 사용합니다.

"item" : [ [ "L", "Z" ] ], "ratings" : [ [3.0, 6.0] ]

또 다른 예를 들어, 중첩 문서에서 스칼라 필드가 속하는 위치를 생각해 보겠습니다. 인스턴스, 다음 문서가 포함된 survey collection을 만듭니다.

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

스칼라 필드 "item.name", "item.manufactured" 및 배열 필드 ratings 에 복합 멀티키 인덱스를 생성합니다.

db.survey.createIndex( { "item.name": 1, "item.manufactured": 1, ratings: 1 } )

스칼라 필드에 쿼리 조건자를 지정하는 다음 작업을 고려하세요.

db.survey.find( {
"item.name": "L" ,
"item.manufactured": 2012
} )

이 쿼리의 경우 MongoDB는 다음과 같은 결합된 바운드를 사용할 수 있습니다.

"item.name" : [ ["L", "L"] ], "item.manufactured" : [ [2012.0, 2012.0] ]

이전 버전의 MongoDB는 스칼라 필드에 대해 이러한 경계를 결합할 수 없습니다.

[1] 스칼라 필드는 값이 문서나 배열이 아닌 필드입니다. 예를 들어 값이 문자열 또는 정수인 필드가 스칼라 필드일 수 있습니다. 스칼라 필드는 필드 자체가 배열이나 문서가 아닌 한 문서에 중첩된 필드가 될 수 있습니다. 예를 들어, 문서 { a: { b: { c: 5, d: 5 } } } 에서 cd 는 스칼라 필드인 반면, ab 는 스칼라 필드가 아닙니다.

배열에 내장된 문서가 포함된 경우 내장된 문서에 포함된 필드를 인덱스하려면 인덱스 사양에서 점으로 구분된 필드 이름 을 사용합니다. 인스턴스, 다음과 같은 내장된 문서 배열이 있다고 가정해 보겠습니다.

ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]

score 필드의 점으로 구분된 필드 이름은 "ratings.score" 입니다.

survey2 collection에 item 필드와 ratings 배열 필드가 있는 문서가 포함되어 있다고 가정해 보겠습니다.

{
_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" } ]
}

비배열 필드 item 와 배열 ratings.scoreratings.by 에서 두 필드에 복합 인덱스 를 생성합니다.

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

다음 쿼리는 세 필드 모두에 대한 조건을 지정합니다.

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는 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" 입니다.

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

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

"ratings.score""ratings.by" 필드는 필드 경로 ratings 를 공유합니다. 다음 쿼리는 필드에 를 사용하여 $elemMatch ratings 배열에 조건과 일치하는 단일 요소가 하나 이상 포함되도록 요구합니다.

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

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

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

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

MongoDB는 두 가지 경계를 복합하여 다음의 결합된 경계를 사용할 수 있습니다.

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

쿼리가 인덱싱된 배열 필드의 조건에 조인하지 $elemMatch 않으면 MongoDB는 해당 범위를 복합 할 수 없습니다 . 다음 쿼리를 고려하세요.

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

배열에 내장된 단일 문서가 두 기준을 모두 충족할 필요는 없기 때문에 MongoDB는 경계를 복잡하게 만들지 않습니다 . 복합 인덱스를 사용할 때 MongoDB가 인덱스의 모든 필드를 제한할 수 없는 경우 MongoDB는 항상 인덱스의 선행 필드(이 경우 "ratings.score")를 제한합니다.

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

쿼리가 포함된 필드의 경로에 $elemMatch 을(를) 지정하지 않는 경우(필드 이름 제외) MongoDB는 동일한 배열에 있는 인덱스 키의 경계를 복합 할 수 없습니다 .

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

{
_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" } ]
}

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 는 해당 경로에 있어야 합니다.

그러나 다음 쿼리는 $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 } } } )

돌아가기

멀티키