Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

ESR(동등성, 정렬, 범위) 가이드라인

복합 인덱스 여러 필드를 참조하며 쿼리 응답 시간을 크게 개선할 수 있습니다.

대부분의 경우 ESR(동등성, 정렬, 범위) 가이드라인을 적용하여 인덱스 키를 정렬하면 보다 효율적인 복합 인덱스생성됩니다.

동등성 필드가 항상 먼저 와야 합니다. 동등성 필드를 먼저 배치하면 나머지 인덱스 필드가 정렬된 순서로 유지됩니다. 인덱스의 특정 요구 사항에 따라 다음으로 정렬 또는 범위 필드 사용할지 여부를 선택합니다.

  • 메모리 내 정렬을 피해야 하는 경우 정렬 필드를 범위 필드(ESR) 앞에 배치하세요.

  • 쿼리 의 범위 술어가 매우 선택적인 경우 정렬 필드(ERS) 앞에 둡니다.

쿼리 최적화에 관한 자세한 내용은 explain쿼리 계획을 참조하세요.

MongoDB 특정 인덱스 사용하도록 강제하려면 인덱스를 테스트할 때 커서.hint() (mongosh 메서드) 를 사용합니다.

이 페이지의 예제에서는 sample_mflix 샘플 데이터 세트 의 데이터를 사용합니다. 이 데이터 세트를 자체 관리형 MongoDB deployment 에 로드하는 방법에 대한 자세한 내용은 샘플 데이터 세트 로드를 참조하세요. 샘플 데이터베이스를 수정한 경우 이 페이지의 예제를 실행 하려면 데이터베이스를 삭제하고 다시 만들어야 할 수 있습니다.

'동등성'은 단일 값에 대한 정확한 일치를 나타냅니다. 다음의 정확한 일치 쿼리는 title 필드가 Equilibrium와 정확히 일치하는 문서를 찾기 위해 movies 컬렉션을 스캔합니다.

db.movies.find(
{ title: "Equilibrium" },
{ title: 1, year: 1, cast: 1 }
)
[
{
_id: ObjectId('573a13a3f29313caabd0c8d2'),
year: 2002,
title: 'Equilibrium',
cast: [
'Christian Bale',
'Dominic Purcell',
'Sean Bean',
'Christian Kahrmann'
]
}
]
db.movies.find(
{ title: { $eq: "Equilibrium" } },
{ title: 1, year: 1, cast: 1 }
)
[
{
_id: ObjectId('573a13a3f29313caabd0c8d2'),
year: 2002,
title: 'Equilibrium',
cast: [
'Christian Bale',
'Dominic Purcell',
'Sean Bean',
'Christian Kahrmann'
]
}
]

인덱스 검색은 정확히 일치하는 항목을 효율적으로 사용하여 검사하는 인덱스 키 수를 줄입니다. 동등성 필드가 먼저 와야 합니다.

인덱스 에는 여러 개의 동등 키가 있을 수 있습니다. 이들은 서로에 대해 어떤 순서로든 나타날 수 있지만 모든 동등 키는 정렬 또는 범위 필드 앞에 와야 합니다.

동등성 매치가 선택적으로 진행될수록 인덱싱된 쿼리 효율성이 높아집니다.

'정렬'은 결과의 순서를 결정합니다. 메모리 내 정렬을 피하려면 인덱스 에서 정렬 필드를 범위 앞에 배치합니다.

인덱스 쿼리 에 정렬 키 앞에 오는 모든 접두사 키에 대한 동일성 조건이 포함된 경우에만 키의 하위 집합에 대한 정렬 작업을 지원합니다. 자세한 내용은 인덱스의 정렬 및 접두사가 없는 하위 집합을 참조하세요.

다음 예시 directors 필드 "David Lynch"가 포함된 영화에 대해 movies 컬렉션 쿼리합니다. 출력은 year을 기준으로 정렬됩니다.

db.movies.find(
{ directors: "David Lynch" },
{ title: 1, year: 1 }
).sort( { year: 1 } )
[
{
_id: ObjectId('573a1397f29313caabce77d4'),
title: 'The Elephant Man',
year: 1980
},
{
_id: ObjectId('573a1398f29313caabce9091'),
title: 'Dune',
year: 1984
},
{
_id: ObjectId('573a1398f29313caabce9e12'),
title: 'Blue Velvet',
year: 1986
},
{
_id: ObjectId('573a1399f29313caabced630'),
year: 1992,
title: 'Twin Peaks: Fire Walk with Me'
},
{
_id: ObjectId('573a139af29313caabcf00f0'),
year: 1997,
title: 'Lost Highway'
},
{
_id: ObjectId('573a139ef29313caabcfbc0e'),
year: 1999,
title: 'The Straight Story'
},
{
_id: ObjectId('573a139ef29313caabcfbc36'),
title: 'Mulholland Drive',
year: 2001
},
{
_id: ObjectId('573a13b4f29313caabd40a54'),
title: 'Inland Empire',
year: 2006
}
]

쿼리 성능을 향상하려면 directorsyear 필드에 인덱스를 생성하세요.

db.movies.createIndex( { directors: 1, year: 1 } )
  • directors 가 첫 번째 키인 이유는 동등성 매치이기 때문입니다.

  • year 은 쿼리와 동일한 순서(1)로 인덱싱됩니다.

'범위' 필터는 필드를 스캔합니다. 스캔에는 정확한 일치가 필요하지 않습니다. 이는 범위 필터가 인덱스 키에 느슨하게 바인딩되어 있음을 의미합니다. 쿼리 효율성을 높이려면 범위 경계를 제한하고 동등성 매치 항목을 사용하여 스캔할 문서 수를 줄이세요.

범위 필터는 다음과 유사합니다.

db.movies.find(
{ runtime: { $gte: 1000 } },
{ title: 1, runtime: 1, year: 1, plot: 1 }
)
[
{
_id: ObjectId('573a1397f29313caabce69db'),
plot: 'The economic and cultural growth of Colorado spanning two centuries from the mid-1700s to the late-1970s.',
runtime: 1256,
title: 'Centennial',
year: 1978
},
{
_id: ObjectId('573a1399f29313caabcee1aa'),
plot: 'A documentary on the history of the sport with major topics including Afro-American players, player/team owner relations and the resilience of the game.',
runtime: 1140,
title: 'Baseball',
year: 1994
}
]
db.movies.find(
{ year: { $lt: 1900 } },
{ title: 1, year: 1, plot: 1 }
)
[
{
_id: ObjectId('573a139cf29313caabcf560f'),
plot: 'Two people kiss.',
title: 'The Kiss',
year: 1896
},
{
_id: ObjectId('573a13a0f29313caabd041db'),
plot: 'Two people kiss.',
title: 'The Kiss',
year: 1896
}
]
db.movies.find(
{ type: { $ne: "movie" } },
{ title: 1, year: 1, type: 1 }
)
[
{
_id: ObjectId('573a1395f29313caabce2f03'),
title: 'The Forsyte Saga',
year: 1967,
type: 'series'
},
{
_id: ObjectId('573a1396f29313caabce520d'),
title: 'Scenes from a Marriage',
year: 1973,
type: 'series'
},
{
_id: ObjectId('573a1396f29313caabce5b86'),
title: 'Ironiya sudby, ili S legkim parom!',
year: 1975,
type: 'series'
},
{
_id: ObjectId('573a1397f29313caabce6378'),
title: 'Sybil',
year: 1976,
type: 'series'
},
{
_id: ObjectId('573a1397f29313caabce6443'),
title: 'Jesus of Nazareth',
year: 1977,
type: 'series'
}
]

쿼리 의 범위 술어가 매우 선택적인 경우 정렬 필드 앞에 배치하여 정렬된 문서 수를 줄이고 인메모리 정렬을 허용합니다.

메모리 내 정렬을 방지하려면 정렬 조건자 뒤에 범위 필터하다 배치합니다. 인메모리 정렬에 대한 자세한 내용은 cursor.allowDiskUse()를 참조하세요.

  • $ne 또는 $nin과 같은 부등호 연산자는 등호 연산자가 아니라 범위 연산자입니다.

  • $regex 는 범위 연산자입니다.

  • $in:

    • $in을(를) 단독으로 사용하면 일련의 동등성 매치를 수행하는 등호 연산자입니다.

    • .sort()와 함께 $in을 사용하는 경우:

      • $in 배열 요소가 201 개 미만인 경우 SORT_MERGE 단계를 사용하여 인덱스 에 지정된 정렬 순서대로 요소가 확장된 다음 병합됩니다. 이렇게 하면 작은 배열의 성능이 향상됩니다. 이 경우 $in 는 ESR이 있는 동등성 술어와 유사합니다.

      • $in 에 201 개 이상의 요소가 있는 경우 요소는 범위 연산자 처럼 정렬됩니다. 이 경우 작은 배열의 성능 향상이 이루어지지 않습니다. 인덱스 의 후속 필드를 정렬에 사용할 수 없으며 $in 는 ESR이 있는 범위 술어와 유사합니다.

      • 일반적으로 작은 배열에 $in 연산자를 사용하는 경우 해당 연산자를 인덱스 사양 앞부분에 포함하세요. 일반적으로 큰 배열을 사용하는 경우 범위 술어를 포함하는 곳에 $in 연산자를 포함합니다.

참고

201 배열 요소의 $in 동작 변경은 모든 MongoDB 버전에서 동일하게 유지된다고 보장되지 않습니다.

다음 쿼리 movies 컬렉션 에서 directors 필드 가 "David Lynch" 이고 runtime 필드 130 분 미만인 영화를 검색합니다. 결과는 year를 기준으로 정렬됩니다.

db.movies.find(
{
directors: "David Lynch",
runtime: { $lt: 130 }
},
{ title: 1, year: 1, runtime: 1 }
).sort( { year: 1 } )
[
{
_id: ObjectId('573a1397f29313caabce77d4'),
runtime: 124,
title: 'The Elephant Man',
year: 1980
},
{
_id: ObjectId('573a1398f29313caabce9e12'),
runtime: 120,
title: 'Blue Velvet',
year: 1986
},
{
_id: ObjectId('573a139ef29313caabcfbc0e'),
year: 1999,
title: 'The Straight Story',
runtime: 112
}
]

쿼리 에는 ESR 가이드라인의 모든 요소가 포함되어 있습니다.

  • directors: "David Lynch" 는 동등성 기반 일치입니다.

  • runtime: { $lt: 130 } 은(는) 범위 기반 일치입니다.

  • year 은 정렬에 사용됩니다.

ESR 가이드라인에 따라 예시 쿼리 대한 최적의 인덱스 다음과 같습니다.

{ directors: 1, year: 1, runtime: 1 }

돌아가기

Strategies

이 페이지의 내용