멀티키 인덱스 바운드
이 페이지의 내용
인덱스 바운드 는 MongoDB가 인덱스를 사용하여 쿼리를 수행할 때 검색하는 인덱스 값의 범위를 정의합니다. 인덱싱된 필드에 여러 쿼리 조건자를 지정하는 경우, MongoDB는 해당 조건자의 경계를 결합하여 경계가 더 작은 인덱스 스캔을 생성하려고 시도합니다. 인덱스 바운드가 작을수록 쿼리 속도가 빨라지고 리소스 사용량이 줄어듭니다.
MongoDB는 교차 또는 복합 경계로 경계를 결합합니다.
멀티키 인덱스의 경계 교차점
경계 교차점은 여러 경계가 겹치는 점을 나타냅니다. 예를 들어, [ [ 3, Infinity ] ]
및 [ [
-Infinity, 6 ] ]
경계가 주어지면 경계의 교집합은 [ [ 3, 6
] ]
가 됩니다.
인덱싱된 배열 필드 가 주어졌을 때 배열 에 여러 쿼리 조건자를 지정하고 멀티키 인덱스 를 사용하여 쿼리 를 수행하는 쿼리 를 가정해 보겠습니다. MongoDB 는 $elemMatch
연산자 가 쿼리 술어를 조인하는 경우 다중 키 인덱스 바운드 를 교차할 수 있습니다.
예제: 경계 교차
다음 예제는 MongoDB가 바운드 교차를 사용하여 쿼리할 값의 범위를 더 좁혀 쿼리 성능을 개선하는 방법을 보여줍니다.
멀티키 인덱스 만들기
grades
배열에 멀티키 인덱스 를 생성합니다.
db.students.createIndex( { grades: 1 } )
컬렉션 쿼리하기
다음 쿼리를 실행합니다.
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가 없는 쿼리
쿼리가 배열 필드의 조건에 $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가 복합 경계를 사용하여 보다 효율적인 쿼리 제약 조건을 정의하여 쿼리 성능을 개선하는 방법을 보여줍니다.
복합 멀티키 인덱스 만들기
item
및 ratings
필드에 복합 멀티키 인덱스 를 생성합니다.
db.survey.createIndex( { item: 1, ratings: 1 } )
컬렉션 쿼리하기
다음 쿼리를 실행합니다.
db.survey.find( { item: "XYZ", ratings: { $gte: 3 } } )
앞의 쿼리는 인덱스(item
및 ratings
)의 두 키 모두에 조건을 지정합니다.
술어를 별도로 사용합니다.
item: "XYZ"
술어의 경계는[ [ "XYZ", "XYZ" ]]
입니다.ratings: { $gte: 3 }
술어의 경계는[ [ 3, Infinity ] ]
입니다.
MongoDB는 다음과 같은 결합된 범위를 사용합니다.
{ item: [ [ "XYZ", "XYZ" ] ], ratings: [ [ 3, Infinity ] ] }
예제: 비배열 필드와 다중 배열 필드의 복합 경계
다음 예제는 인덱스에 배열이 아닌 필드와 여러 개의 배열 필드가 포함된 경우 MongoDB가 복합 경계를 사용하는 방법을 보여줍니다.
컬렉션 쿼리하기
다음 쿼리를 실행합니다.
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
컬렉션을 사용합니다.
컬렉션 쿼리하기
다음 쿼리를 실행합니다.
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
쿼리가 공통 경로에서 벗어나는 필드에 $elemMatch
를 지정하는 경우, MongoDB는 동일한 배열에 있는 인덱스 키의 경계를 복합 할 수 없습니다 .
다음 예에서는 분기하는 필드 경로의 $elemMatch
를 보여줍니다.
샘플 collection 채우기
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" } ] } ] )
컬렉션 쿼리하기
다음 쿼리는 필수 경로에 없는 $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 } } } )