Primary로만 쿼리 실행하며, Primary가 없으면 쿼리 실행은 실패(장애 발생하고 fail over 이전)
PrimaryPreferred
가능하면 Primary로 전송하며 장애로 Primary가 없는 경우 Secondary 로 요청
Secondary
Secondary 멤버로만 전송하며, Primary로는 요청하지 않음. 멤버가 2개 이상일 경우 적절히 분산하여 요청
Secondary가 없는 경우 실패 발생
secondaryPreferred
Secondary와 동일하지만 없는 경우 Primary로 요청
nearest
쿼리 요청 응답시간이 가장 빠른 멤버로 요청 (Primary, Secondary 고려 안함)
동일한 대역에서는 미흡하지만, 레플리카 셋이 글로벌하게 분산되어 멤버들간의 응답시간이 차이가 나는 경우 적절
샤딩 환경의 중복 Document 처리
샤딩된 클러스터는 2가지 경우에만 Document 샤드의 소유권(Ownership)을 체크
쿼리에 샤드의 메타 정보 버전이 포함된 경우
쿼리의 조건에 샤드 키가 포함된 경우
청크가 이동될 때마다 컨피그 서버의 메타 정보가 변경됨(메타 정보의 버전이 1씩 증가)
버전 정보를 쿼리 실행시마다 전달하는데, 버전이 포함된 쿼리를 'Versioned Query'라고 명칭
청크가 이동되더라도 한 시점의 일괄된 데이터를 보장하는 이유가 버전 정보를 포함하고 있기 때문
하지만 Primary에서 실행한 경우만 Versioned Query를 사용하며 Secondary에서는 버전 정보를 포함하지 않음(Unversioned Query)
Shard key를 포함한 쿼리의 경우 특정 샤드로만 쿼리가 전달되므로 해당 샤드가 가진 청크에 포함된 Document만 반환
Shard Key가 없으며, Secondary에서 조회하는 경우 Document의 중복이 발생 가능성 존재
[ Multi-Document Transaction]
Mongodb Client API도 반드시 4.2 버전으로 사용
4.4 부터 명시적으로 Transaction 내에서 collection 을 생성 가능(Client API 또한 4.4로 사용해야 가능)
MongoDB 버전 4.0부터 제공되었지만, Replica Sets 환경에서 만 지원되었으며 4.2부터 Shard-Cluster 환경에서도 지원
Multi-Document Transation 은 여러 작업, Collection, DB에 적용할 수 있으며 Transaction 이 Commit 되면 변경된 모든 데이터를 저장하고 Rollback 되면 모든 데이터 변경을 취소
Commit 이 확정될 때까지 변경 중인 데이터는 누구도 참조할 수 없음( dirty_read : no)
Embedded Document 및 Array 구조와 같은 단일-Dcoument Transaction 에 비해 성능지연 문제가 발생할 가능성이 있기 때문에, 이를 대체해서 사용하면 안됨
FeatureCompatibility Version(fCV) 4.0 이후 환경에서 사용할 수 있으며 wiredTiger Storage Engine과 In-Memory Storage Engine에서 만 사용할수 있음(admin DB에서 설정 가능)db.adminCommand({ getParameter:1, featureCompatibilityVersion:1})
만약 collation option 없이 생성했다가 collation option 넣은 후에 동일하게 생성하려고 해도 생성이 안되며 기존 Index 삭제 후 재생성 해야함
[ Default Indexes : _id]
Collection 생성 시, 별도로 생성하지 않는다면, 기본적으로 _id field에 대해서 Index가 생성
unique Index이며 삭제할 수 없음
PK나 Secondary index나 모두 내부는 동일하기에 Cluster index 개념이 없음
[ Single Field Indexes ]
1개의 필드로 생성된 것을 Single Field Indexes
Index는 생성한 Field를 기준으로 정렬
[ Compound(Composite) Index ]
2개 이상의 필드가 연결된 것을 Compound Indexes
각각 다른 방식으로 정렬하여 생성 가능
[ Multikey Indexes ]
document 내의 document 가 존재하는 embedded document 또는 array 형태의 Field에 Index를 생성
Multikey Index 의 경우 shard key로 사용될 수 없음
shard key는 하나의 chunk로 매핑되어야 하는데, 여러개의 엔트리가 들어 있는 형태로는 불가능
Multi-key index는 커버링 인덱스 처리가 불가능
필드가 array인데 Index 생성하면 자동으로 multikey 인덱스로 생성
Unique Multi-key index는 document 내에서 Unique 가 아닌 Collection 내에서 Unique 함
Compound + Multikey Index에서는 하나의 Multikey 만 포함 가능
또한, 문제없이 compound + Multikey index로 생성되어 있는 경우 그 중 single field에 array 형태로 insert,update 를 시도하면 에러가 발생
ex 1) 아래와 같이 a,b 필드가 array 인 경우 {a:1, b:1} 이런식으로 2개의 compound multikey index를 생성할 수 없다.
{ _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" }
ex 2) {a:1, b:1} 이런 형태로 정상적으로 index가 문제 없이 생성되어 있는 collection 형태에서, 하나의 document에 a,b를 array 형태로 변경 시 문제 발생
{ _id: 1, a: [1, 2], b: 1, category: "A array" } <- b를 array 형태로 document 를 추가 수정 시 fail 발생
{ _id: 2, a: 1, b: [1, 2], category: "B array" } <- a를 array 형태로 document 를 추가 수정 시 fail 발생
ex3) compound + multikey index를 여러 array 에 사용하고 싶은 경우 아래와 같이 설계하면 사용 가능 { "a.x": 1, "a.z": 1 }
{ _id: 1, a: [ { x: 5, z: [ 1, 2 ] }, { z: [ 1, 2 ] } ] }
{ _id: 2, a: [ { x: 5 }, { z: 4 } ] }
[ Text Indexes ]
문자열 내용에 대한 텍스트 검색 쿼리를 지원
문자열 또는 문자열 요소의 배열인 모든 필드가 포함
하나의 Collection에 하나의 text index만 생성 가능
하나의 text index 생성 시 Compound로 생성 가능
생성하려는 Field에 text 로 명시 (다른 Index 생성과 다른 방식)
text Index 생성하게 되면 기본적으로 해당 "field명_text" 명으로 생성
$meta 를 이용하여 검색하는 text에 대해 가중치를 제공 가능
mongodb에서 한글에 대해서 ngram, 형태소분석을 기본적으로 제공하지 않고 구분자 기반(공백문자) 기준으로 인덱싱 처리함
한 단어의 부분에 대해서도 검색을 가능하게 하려면 ngram full text index 기능을 사용해야함
# text Index 생성 방법
db.array.createIndex({"month_data":"text"})
# Compound 으로 생성 방법
db.reviews.createIndex(
{
subject: "text",
comments: "text"
}
)
#가중치 $meta 를 이용하여 sort 진행
db.array.find({$text:{$search:"서울"}},{score:{$meta: "textScore"}}).sort({score:{$meta:"textScore"}}).pretty()
#Wildcard Text Index
db.collection.createIndex( { "$**": "text" } )
MongoDB 인덱스를 생성하는 경우 (Foreground) Collection Lock 이 걸리게 된다.(쿼리 웨이팅 발생, 단 빠르게 생성) , (Session Blocking 발생-순간)
다만, Background Index로 생성하는 경우 Lock을 피할수 있기에 동시 사용성이 증가
Background Index 생성 시 해당 collection으로 session유입 시 Index생성이 잠시 중단 되었다가 완료 되면 다시 시작 (Foreground Index보다 생성 시간이 늦어짐)
Index 생성이 완료 되면 그 때 OpLog에 작성이 되며, 이 것을 받아 Secondary에서도 동일하게 Background로 시작(v2.4의 경우 Secondary에서는 Foreground로 생성 되는 버그. 주의)
Collection의 Document가 많거나 Session 유입이 아주 많다면 세컨드리에서 포그라운드로 먼저 생성 후 프라이머리와 교체하는 것도 방법
RDBMS의 경우 인덱스 생성 시 버퍼 공간을 사용하지만, 몽고 디비의 경우 따로 버퍼를 사용하지 않으며 트랜잭션로그(Undo Log)를 사용하지도 않기 때문에 오래 걸릴수도 있지만, 반대로 단순하기 때문에 버퍼 영역으로 인해 실패하거나 DB에 문제를 일으키지 않는 장점
인덱스 삭제의 경우도 메타 정보를 변경하고 인덱스와 연관된 데이터 파일만 삭제하면 되므로 매우 빠르게 진행(점검을 걸거나 할 필요 없음, 하지만 한순간 데이터베이스 잠금을 필요로 하므로 쿼리 처리량 낮은 시점에 삭제하는 것이 좋음)
Background Index 생성 시, DB가 재시작(인덱스 빌드 프로세스를 강제 종료) 된다면 Index도 DB가 시작되면서 다시 시작하게 됨. 이 때 Foreground로 시작. 이 때 indexBulidRetry 옵션을 False로 설정하면 막을 수 있음
생성되는 지 체크하기 위해서 MongoDB Log나 OpLog를 통해 세컨더리에 생성 되었는지 확인 하면 됨