Docs Menu
Docs Home
/
MongoDB 매뉴얼
/ /

부분 인덱스

이 페이지의 내용

  • 부분 인덱스 생성하기
  • 행동
  • 제한 사항
  • 예시

부분 인덱스는 지정된 필터 표현식을 충족하는 컬렉션의 문서만 인덱싱합니다. 컬렉션에 있는 문서의 하위 집합을 인덱싱하면 부분 인덱스의 스토리지 요구 사항이 줄어들고 인덱스 생성 및 유지 관리에 드는 성능 비용이 절감됩니다.

partial 인덱스를 생성하려면 partialFilterExpression 옵션과 함께 db.collection.createIndex() 메서드를 사용합니다. partialFilterExpression 옵션은 다음을 사용하여 필터 조건을 지정하는 문서를 허용합니다.

  • 등식 표현식(예 field: value 또는 $eq 연산자 사용),

  • $exists: true 표현식입니다,

  • $gt, $gte, $lt, $lte expressions,

  • $type 표현식,

  • $and 연산자

  • $or 연산자

  • $in 연산자

예를 들어, 다음 작업은 rating 필드가 5보다 큰 문서만 인덱싱하는 복합 인덱스를 만듭니다.

db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

모든 MongoDB 인덱스 유형partialFilterExpression 옵션을 지정할 수 있습니다. 시계열 컬렉션의 TTL 인덱스에 partialFilterExpression를 지정하는 경우 컬렉션의 metaField에 대해서만 필터링할 수 있습니다.

다음도 참조하세요.

MongoDB Compass에서 인덱스를 관리하는 방법을 알아보려면 인덱스 관리를 참조하세요.

MongoDB는 인덱스를 사용하여 불완전한 결과 집합이 생성되는 경우 쿼리 또는 정렬 작업에 부분 인덱스를 사용하지 않습니다.

부분 인덱스를 사용하려면 쿼리가 필터 표현식 (또는 필터 표현식의 부분 집합을 지정하는 수정된 필터 표현식)을 쿼리 조건의 일부로 포함해야 합니다.

예를 들어 다음 인덱스가 있다고 가정해 보겠습니다.

db.restaurants.createIndex(
{ cuisine: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

다음 쿼리는 쿼리 조건에 인덱스 필터 표현식 rating: { $gt: 5 }에 부합하는 문서의 하위 집합과 일치하는 조건 rating: { $gte: 8 }이 포함되어 있으므로 해당 인덱스를 사용할 수 있습니다.

db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } )

하지만 다음 쿼리에서는 cuisine 필드의 부분 인덱스를 사용할 수 없습니다. 인덱스를 사용하면 결과 집합이 불완전해지기 때문입니다. 특히 쿼리 조건자에는 조건 rating: { $lt: 8 }이 포함되어 있는 반면, 인덱스에는 필터 rating: { $gt: 5 }가 있습니다. 즉, { cuisine: "Italian", rating: { $lt: 8 } } 쿼리는 인덱싱된 문서보다 더 많은 문서 (예: 평점이 1인 이탈리아 레스토랑)와 일치합니다.

db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } )

마찬가지로, 다음 쿼리는 쿼리 조건자에 필터 표현식이 포함되어 있지 않고 인덱스를 사용하면 불완전한 결과 집합이 반환되기 때문에 부분 인덱스를 사용할 수 없습니다.

db.restaurants.find( { cuisine: "Italian" } )

부분 인덱스는 Sparse 인덱스보다 선호 되어야 합니다. 부분 인덱스는 다음과 같은 이점을 제공합니다.

  • 어떤 문서가 색인화되는지 더 효과적으로 제어할 수 있음.

  • Sparse 인덱스에서 제공하는 기능의 상위 집합.

Sparse 인덱스는 인덱스된 필드의 존재 여부에 전적으로 기반하여 문서를 선택합니다. 복합 인덱스의 경우 인덱스된 필드의 존재 여부에 따릅니다.

부분 인덱스는 지정된 필터를 기반으로 인덱스 항목을 결정합니다. 필터는 인덱스 키 이외의 필드를 포함할 수 있으며 존재 확인 이외의 조건을 지정할 수 있습니다. 예를 들어, 부분 인덱스는 Sparse 인덱스와 동일한 동작을 구현할 수 있습니다.

db.contacts.createIndex(
{ name: 1 },
{ partialFilterExpression: { name: { $exists: true } } }
)

이 부분 인덱스는 name 필드에 대해 Sparse 인덱스와 동일한 쿼리를 지원합니다.

그러나 부분 인덱스는 인덱스 키 이외의 필드에 필터 표현식을 지정할 수도 있습니다. 예를 들어 다음 작업은 부분 인덱스을 생성합니다. 여기서 인덱스는 name 필드에 있지만 필터 표현식은 email 필드에 있습니다.

db.contacts.createIndex(
{ name: 1 },
{ partialFilterExpression: { email: { $exists: true } } }
)

쿼리 옵티마이저가 이 부분 인덱스를 선택하려면 쿼리 조건이 name 필드에 대한 조건을 포함해야 하며 email 필드에 대해 null이 아닌 일치도 포함해야 합니다.

예를 들어, 다음 쿼리는 name 필드에 대한 조건과 email 필드에 대한 null이 아닌 일치 항목을 모두 포함하므로 인덱스를 사용할 수 있습니다.

db.contacts.find( { name: "xyz", email: { $regex: /\.org$/ } } )

그러나 다음 쿼리는 필터 표현식 { email: { $exists: true } }에서 허용되지 않는 email 필드에 null 일치를 포함하고 있기 때문에 인덱스를 사용할 수 없습니다.

db.contacts.find( { name: "xyz", email: { $exists: false } } )

부분 인덱스는 TTL 인덱스일 수도 있습니다. 부분 TTL 인덱스는 지정된 필터 표현식과 일치하며 해당 문서만 만료됩니다. 자세한 내용은 필터 조건이 있는 문서 만료를 참조하세요.

  • partialFilterExpression 옵션과 sparse 옵션을 모두 지정할 수 없습니다.

  • _id 인덱스는 부분 인덱스가 될 수 없습니다.

  • 샤드 키 인덱스는 부분 인덱스가 될 수 없습니다.

  • 클라이언트 사이드 필드 수준 암호화 또는 Queryable Encryption을 사용하는 경우 partialFilterExpression 은 암호화된 필드를 참조할 수 없습니다.

MongoDB 7.3 부터는 데이터 정렬을 사용하는 동일한 인덱스 키와 동일한 부분 표현식을 가진 부분 인덱스를 생성할 수 없습니다.

기존의 동등한 인덱스가 있는 MongoDB 7.3 데이터베이스의 경우 인덱스는 유지되지만 첫 번째 동등한 인덱스만 쿼리에 사용됩니다. 이는 MongoDB 7.3 이전 버전과 동일한 동작입니다.

예시 는 등가 인덱스 예시를 참조하세요.

다음과 비슷한 문서가 포함된 restaurants 컬렉션이 있다고 가정해 봅시다.

{
"_id" : ObjectId("5641f6a7522545bc535b5dc9"),
"address" : {
"building" : "1007",
"coord" : [
-73.856077,
40.848447
],
"street" : "Morris Park Ave",
"zipcode" : "10462"
},
"borough" : "Bronx",
"cuisine" : "Bakery",
"rating" : { "date" : ISODate("2014-03-03T00:00:00Z"),
"grade" : "A",
"score" : 2
},
"name" : "Morris Park Bake Shop",
"restaurant_id" : "30075445"
}

rating.grade 필드가 A인 문서의 인덱스만 생성하도록 선택하여 boroughcuisine 필드에 부분 인덱스를 추가할 수 있습니다.

db.restaurants.createIndex(
{ borough: 1, cuisine: 1 },
{ partialFilterExpression: { 'rating.grade': { $eq: "A" } } }
)

그런 다음 restaurants 컬렉션에 대한 다음 쿼리는 부분 인덱스를 사용하여 rating.gradeA인 Bronx의 레스토랑을 반환합니다.

db.restaurants.find( { borough: "Bronx", 'rating.grade': "A" } )

그러나 다음 쿼리는 쿼리 조건자에 rating.grade 필드가 포함되어 있지 않기 때문에 부분 인덱스를 사용할 수 없습니다.

db.restaurants.find( { borough: "Bronx", cuisine: "Bakery" } )

부분 인덱스는 지정된 필터 표현식을 충족하는 컬렉션의 문서만 인덱싱합니다. partialFilterExpression고유 (Unique) 제약 조건을 모두 지정하는 경우 고유 제약 조건은 필터 표현식을 충족하는 문서에만 적용됩니다. 고유 제약 조건이 있는 부분 인덱스는 문서가 필터 기준을 충족하지 않는 경우 고유 제약 조건을 충족하지 않는 문서의 삽입을 막지 않습니다.

예를 들어 users 컬렉션에는 다음과 같은 문서가 포함되어 있습니다.

{ "_id" : ObjectId("56424f1efa0358a27fa1f99a"), "username" : "david", "age" : 29 }
{ "_id" : ObjectId("56424f37fa0358a27fa1f99b"), "username" : "amanda", "age" : 35 }
{ "_id" : ObjectId("56424fe2fa0358a27fa1f99c"), "username" : "rajiv", "age" : 57 }

다음 작업은 username 필드에 대한 고유 제약 조건과 부분 필터 식 age: { $gte: 21 }을 지정하는 인덱스를 생성합니다.

db.users.createIndex(
{ username: 1 },
{ unique: true, partialFilterExpression: { age: { $gte: 21 } } }
)

지정된 사용자 이름을 가진 문서가 이미 존재하고 age 필드가 21보다 크므로 인덱스는 다음 문서의 삽입을 막습니다.

db.users.insertMany( [
{ username: "david", age: 27 },
{ username: "amanda", age: 25 },
{ username: "rajiv", age: 32 }
] )

하지만 고유 제약 조건은 age 21보다 크거나 같은 문서에만 적용되므로 중복된 사용자 이름이 있는 다음 문서는 허용됩니다.

db.users.insertMany( [
{ username: "david", age: 20 },
{ username: "amanda" },
{ username: "rajiv", age: null }
] )

MongoDB 7.3 부터는 데이터 정렬을 사용하는 동일한 인덱스 키와 동일한 부분 표현식을 가진 부분 인덱스를 생성할 수 없습니다.

기존의 동등한 인덱스가 있는 MongoDB 7.3 데이터베이스의 경우 인덱스는 유지되지만 첫 번째 동등한 인덱스만 쿼리에 사용됩니다. 이는 MongoDB 7.3 이전 버전과 동일한 동작입니다.

이전 MongoDB 버전에서는 두 개의 동등한 인덱스를 생성할 수 있습니다. 다음 예시 에서는 pizzas 컬렉션 과 index0index1 라는 두 개의 동등한 인덱스를 만듭니다.

// Create the pizzas collection
db.pizzas.insertMany( [
{ _id: 0, type: "pepperoni", size: "small", price: 4 },
{ _id: 1, type: "cheese", size: "medium", price: 7 },
{ _id: 2, type: "vegan", size: "large", price: 8 }
] )
// Create two equivalent indexes with medium pizza sizes
db.pizzas.createIndex(
{ type: 1 },
{ name: "index0",
partialFilterExpression: { size: "medium" },
collation: { locale: "en_US", strength: 1 }
}
)
db.pizzas.createIndex(
{ type: 1 },
{ name: "index1",
partialFilterExpression: { size: "MEDIUM" },
collation: { locale: "en_US", strength: 1 }
}
)

두 인덱스가 동일한 피자 크기를 지정하고 부분 필터하다 표현식 에서 텍스트 대소문자만 다르기 때문에 인덱스는 동일합니다. 쿼리에는 하나의 인덱스 만 사용되며, 이는 가장 먼저 생성된 인덱스 이며, 이전 예시 에서는 index0 입니다.

MongoDB 7.3 부터는 두 번째 인덱스 (index1)를 생성할 수 없으며 이 오류가 반환됩니다.

MongoServerError: Index already exists with a different name: index0

7.3 이전 MongoDB 버전에서는 인덱스를 만들 수 있지만 이러한 쿼리에는 첫 번째 인덱스 (index0)만 사용됩니다.

db.pizzas.find( { type: "cheese", size: "medium" } ).collation(
{ locale: "en_US", strength: 1 }
)
db.pizzas.find( { type: "cheese", size: "MEDIUM" } ).collation(
{ locale: "en_US", strength: 1 }
)
db.pizzas.find( { type: "cheese", size: "Medium" } ).collation(
{ locale: "en_US", strength: 1 }
)

돌아가기

숨김