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

고유 인덱스

이 페이지의 내용

  • 고유 색인 만들기
  • 행동

고유 인덱스는 인덱싱된 필드에 중복된 값이 저장되지 않도록 합니다. 즉, 인덱싱된 필드에 고유성을 적용합니다. 기본적으로 MongoDB는 컬렉션 생성 중에 _id 필드에 고유 인덱스를 생성합니다.

참고

새로운 내부 형식

MongoDB 4.2부터는 eatureCompatibilityVersion (fCV)이 4.2 이상인 경우, 이전 MongoDB 버전과 호환되지 않는 고유 인덱스에 대해 새로운 내부 형식을 사용합니다. 새로운 형식은 기존 고유 인덱스와 새로 생성되거나 재구축된 고유 인덱스 모두에 적용됩니다.

MongoDB Atlas에서 호스팅되는 배포서버에 대해 UI에서 고유 인덱스를 생성하고 관리할 수 있습니다.

고유 인덱스를 생성하려면 true로 설정된 unique 옵션이 있는 db.collection.createIndex() 메서드를 사용합니다.

db.collection.createIndex( <key and index type specification>, { unique: true } )

예를 들어 members 컬렉션의 user_id 필드에 고유 인덱스를 만들려면 mongosh에서 다음 연산을 사용합니다.

db.members.createIndex( { "user_id": 1 }, { unique: true } )

복합 인덱스에 대해서도 고유 제약 조건을 적용할 수 있습니다. 복합 인덱스에 고유 제약 조건을 사용하는 경우, MongoDB는 인덱스 키 값 조합에 대한 고유성을 강제합니다.

예를 들어 members 컬렉션의 groupNumber, lastnamefirstname 필드에 고유 인덱스를 만들려면 mongosh에서 다음 연산을 사용합니다.

db.members.createIndex( { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } )

생성된 인덱스는 groupNumber, lastname 그리고 firstname 값의 조합에 대해 고유성을 강제합니다.

다른 예로 다음 문서가 있는 컬렉션을 생각해 보겠습니다.

{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }

a.loca.qty에 고유한 복합 멀티키 인덱스 만들기.

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

고유 인덱스는 a.loca.qty조합에 대해 고유성을 강제하므로, 고유 인덱스는 다음 문서를 컬렉션에 삽입할 수 있게 합니다.

db.collection.insertMany( [
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] },
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }
] )

다음도 참조하세요.

컬렉션에 이미 인덱스에 대한 고유 제약 조건을 위반하는 데이터가 포함되어 있는 경우, MongoDB는 지정된 인덱스 필드에 고유 인덱스를 만들 수 없습니다.

해시 인덱스에고유한 제약 조건을 지정할 수 없습니다.

복제본 세트 및 샤딩된 클러스터의 경우 롤링 절차를 사용하여 고유 인덱스를 만들려면 절차가 진행되는 동안 컬렉션에 대한 모든 쓰기를 중지해야 합니다. 절차가 진행되는 동안 컬렉션에 대한 모든 쓰기를 중지할 수 없다면 롤링 절차를 사용하지 마세요. 대신 다음 방법으로 컬렉션에 대한 고유한 인덱스를 다음과 같이 구축하세요.

고유 제약 조건은 컬렉션의 개별 문서에 적용됩니다. 즉, 고유 인덱스는 별도의 문서가 인덱스된 키에 대해 동일한 값을 갖는 것을 방지합니다.

제약 조건은 개별 문서에 적용되므로 고유한 멀티키 인덱스의 경우 문서에 배열 요소를 가질 수 있으며, 해당 문서의 인덱스 키 값이 다른 문서의 인덱스 키 값과 중복되지 않는 한 인덱스 키 값이 반복될 수 있습니다. 이 경우 반복되는 인덱스 항목은 인덱스에 한 번만 삽입됩니다.

예를 들어 다음 문서가 있는 컬렉션을 생각해 보겠습니다.

{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] }
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }

a.loca.qty에 고유한 복합 멀티키 인덱스를 생성합니다.

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

고유 인덱스는 컬렉션의 다른 문서가 인덱스 키 값 { "a.loc": "B", "a.qty": null }을 가지고 있지 않는 경우, 다음 문서를 컬렉션에 삽입하는 것을 허용합니다.

db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )

고유한 단일 필드 인덱스에서 인덱싱된 필드에 대해 문서가 null 값이거나 누락된 경우, 인덱스는 해당 문서에 대해 null 값을 저장합니다. 고유 제약조건으로 인해 단일 필드 고유 인덱스는 해당 인덱스 항목에 null 값을 포함하는 하나의 문서만 포함할 수 있습니다. 인덱스 항목에 null 값이 있는 문서가 두 개 이상 있으면 중복 키 오류로 인해 인덱스 빌드가 실패합니다.

예를 들어 컬렉션에 x에 대한 고유한 단일 필드 인덱스가 있습니다.

db.collection.createIndex( { "x": 1 }, { unique: true } )

컬렉션에 x 필드가 누락된 문서가 아직 포함되어 있지 않은 경우, 고유 인덱스는 x 필드 없이 문서의 삽입을 허용합니다.

db.collection.insertOne( { y: 1 } )

그러나 컬렉션에 x 필드가 없는 문서가 이미 포함되어 있는 경우 필드 x 없이 문서를 삽입할 수 없습니다.

db.collection.insertOne( { z: 1 } )

x 필드 값에 대한 고유 제약 조건 위반으로 인해 작업이 문서를 삽입하지 못했습니다.

WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
}
})

고유 복합 인덱스에서 하나 이상의 인덱스된 필드에 대해 문서가 null 값을 가지거나 값이 누락된 경우, 인덱스는 문서의 인덱스 항목에서 각 null 또는 누락된 필드에 대해 null 값을 저장합니다. 고유한 제약 조건으로 인해 고유한 복합 인덱스는 인덱스 항목의 모든 인덱스 필드에 대해 null 값을 가진 문서 하나만 허용합니다. 모든 인덱싱된 필드에 null 값이 있는 인덱스 항목이 두 개 이상 있는 경우 중복 키 오류가 발생하여 인덱스 작성이 실패합니다. MongoDB는 각 인덱스 항목이 고유하기만 하면 고유 복합 인덱스에 누락된 필드가 있는 여러 문서를 허용합니다.

예를 들어 컬렉션 studentsname, agegrade 필드에 고유한 복합 인덱스를 가지고 있습니다:

db.students.createIndex(
{
"name": 1,
"age": -1,
"grade": 1
},
{ unique: true }
)

컬렉션에 동일한 문서가 아직 없는 경우 고유 복합 인덱스는 grade 필드가 모두 없는 다음 문서를 삽입을 허용합니다.

db.students.insertMany(
{ "name": "Meredith", "age": 12 },
{ "name": "Olivia", "age": 11 },
{ "name": "Benjamin" }
)

그러나 컬렉션의 다른 문서와 동일한 인덱스 키 (name, agegrade의 값)을 가진 문서는 삽입할 수 없습니다.

db.students.insertOne( { name: "Meredith", age: 12 } )

name, agegrade 필드 값에 대한 고유 제약 조건 위반으로 인해 작업이 문서 삽입 작업이 실패합니다.

WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" :
"E11000 duplicate key error collection: test.students
index: name_1_age_-1_grade_1
dup key: { name: "Meredith", age: 12, grade: null }
}
} )

또한, 문서가 고유하지만 기존 인덱스 항목과 인덱스 키를 공유하는 경우에도 문서를 삽입할 수 없습니다.

db.students.insertOne( { name: "Olivia", "age": 11, "favorite color": "red"} )

name, agegrade 필드 값에 대한 고유 제약 조건 위반으로 인해 작업이 문서 삽입 작업이 실패합니다.

WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" :
"E11000 duplicate key error collection: test.students
index: name_1_age_-1_grade_1
dup key: { name: "Olivia", age: 11, grade: null }
}
} )

부분 인덱스는 지정된 필터 표현식을 충족하는 컬렉션의 문서만 인덱싱합니다. partialFilterExpression과(와) 고유 제약 조건을 모두 지정하는 경우 고유 제약 조건은 필터 표현식을 충족하는 문서에만 적용됩니다.

고유 제약 조건이 있는 부분 인덱스는 문서가 필터 기준을 충족하지 않는 경우 고유 제약 조건을 충족하지 않는 문서의 삽입을 막지 않습니다. 이에 대한 예제는 고유 제약 조건이 있는 부분 인덱스를 참조하세요.

해시 인덱스에는 고유한 제약 조건을 지정할 수 없습니다.

범위가 지정된 샤딩된 컬렉션의 경우 다음 인덱스만 고유할 수 있습니다.

  • 인덱스가 될 수 있습니다.

  • 샤드 키가 접두사복합 인덱스

  • 인덱스는 기본 _id 인덱스입니다. 그러나 _id 인덱스는 _id 필드가 샤드 키 또는 샤드 키의 접두사가 아닌 경우에만 샤드별 고유성 제약 조건을 집행합니다.

    중요

    고유성 및 _id 인덱스

    _id 필드가 샤드 키 또는 샤드 키의 접두사가 아닌 경우 _id 인덱스는 샤드 전체가 아닌 샤드당 고유성 제약 조건만 집행합니다.

    예를 들어, 샤드 키 {x: 1}로 두 샤드 A와 B에 걸쳐 있는 샤드된 컬렉션을 생각해 보십시오. _id 키는 샤드 키의 일부가 아니므로 컬렉션에는 샤드 A에 _id 값이 1인 문서가 있고, 샤드 B에 _id 값이 1인 또 또 다른 문서가 있을 수 있습니다.

    _id 필드가 샤드 키가 아니거나 샤드 키의 접두사가 아닌 경우, MongoDB는 애플리케이션이 _id 값의 고유성을 샤드 전체에 걸쳐 집행할 것으로 예상합니다.

고유한 인덱스 제약 조건은 다음을 의미합니다.

  • 샤딩할 collection의 경우 collection에 다른 고유 인덱스가 있으면 collection을 샤딩할 수 없습니다.

  • 이미 샤딩된 collection의 경우 다른 필드에 고유 인덱스를 만들 수 없습니다.

MongoDB 5.0부터는 동일한 키 패턴을 가진 고유한 스파스 인덱스와 고유한 비스파스 인덱스가 단일 컬렉션에 존재할 수 있습니다.

이 예시에서는 동일한 키 패턴과 다른 sparse 옵션을 사용하여 여러 인덱스를 만듭니다.

db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )

sparse 옵션을 사용하거나 사용하지 않고 동일한 키 패턴으로 기본 인덱스를 생성할 수도 있습니다.

db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } )
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )

MongoDB 5.0부터는 기본 인덱스와 고유 인덱스가 동일한 키 패턴으로존재할 수 있습니다.

키 패턴의 이러한 중복은 이미 인덱싱된 필드에 고유 인덱스를 추가할 수 있게 합니다.

이 예제에서는

키 패턴 { score : 1 }으로 기본 인덱스를 생성하고 문서 3개를 삽입합니다.

db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
db.scoreHistory.insert( { score : 1 } )
db.scoreHistory.insert( { score : 2 } )
db.scoreHistory.insert( { score : 3 } )

동일한 키 패턴 { score : 1 } 을 사용하여 고유 인덱스를 만듭니다.

db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )

고유 인덱스로 인해 실패한 중복된 score 문서를 삽입해 보십시오.

db.scoreHistory.insert( { score : 3 } )
← TTL을 설정하여 컬렉션에서 데이터 만료하기

이 페이지의 내용