1. MongoDB에서 Index의 대소문자는 엄격히 구분
  2. Document를 update할 때 해당 Index Key만 변경되지만 변경되는 Document 크기가 기존 Extent 공간 크기보다 큰 경우 더 큰 Extent 공간으로 마이그레이션 될 수 있기 때문에 성능 저하 현상이 발생 ( 설계 시 Extent 공간도 고려)
  3. Sort() / limit()은 함께 사용하는 것이 성능에 좋음
    • Index를 활용하면 Sort된 형태로 반환되며 limit을 이용하면 불필요한 검색량을 줄여줄 수 있어서 효과로 예상
  4. reIndex는 기존 Index 제거 후 생성 됨 
  5. B-Tree Index
    • 인덱스를 생성 시, 인덱스는 해당 Field의 값을 가지고, Document들을 가르키는 포인터 값으로 이뤄진 B-Tree Index
    • Field 값 + Document를 가르키는 포인터 값
  6. Collection 생성 시 _id 필드에 유니크 인덱스를 자동 생성(별도의 _id를 명시 하지 않는 것을 추천 / 내부 인덱스 생성)
  7. Cluster Index 개념이 존재하지 않기에 PK나 Secondary Index 나 내부 구조는 동일
    • Index를 이용해 Document 검색할 때 Index -> Hiden Field(Record-Id) -> Data접근 하여 총 2번의 인덱스 검색
    • Hiden Field로 생성되는 Record-Id 인덱스가 ClusterIndex 이지만 사용자는 이것을 생성하거나 사용할 수 없기 때문에 ClusterIndex는 없다고 봐야 한다.
  8. 인덱스 생성 시 서브Document 를 이용하여 생성은 가능하지만, 인덱스는 압축을 하지 않기에 자칫 인덱스 사이즈가 커지므로 인덱스로써 역효과를 가져올 수 있음
    • WT Cache 상태에서는 데이터는 non압축 상태이지만, Index는 메모리 상 뿐만 아니라 디스크에도 prefix 압축된 상태로 사용(메모리의 효율성을 증대 가능)
    • SubDocument 에 Index 생성 시 어떻게 find를 할 것인지 반드시 고민 후에 생성해야 하며 순서 또한 보장해야 함
      • v4.2.2-3
      • subdocument 내 모든 필드 내역을 find 조건에 작성 해야 하며
      • 순서 또한 맞춰서 검색 조건에 포함
      • Dot으로 검색 한다면, dot 으로 인덱스를 생성
    • 서브 도큐먼트의 필드를 모두 가지고 순서가 같을 때만 인덱스 역활을 할 수 있음 (위와 동일)
    • 필히 참고 : https://www.percona.com/blog/2020/07/24/mongodb-utilization-of-an-index-on-subdocuments/
    • 인덱스도 prefix 압축 사용
    • subdocument
  9. Equal 검색 및 앞 부분 일치할 때만 사용 가능하고, 부등호(부정) 에 비교에서는 사용 불가, 필드값 변형이 일어난 것, 함수 적용 등은 사용 못함(rdbms와 동일)

 

[ 가이드 ]

  1. Equal 검색을 지향합니다.
  2. 조건에 많이 사용하는 Field 쿼리에 대해서 선행 Filed 로 하여 Index 생성
  3. Cardinality 가 좋은 Field 에 대해서 Index 를 생성
  4. 날짜 검색을 해야 한다면, 가급적이면 _id 를 이용한 Range(날짜 지정 범위-$gte and $lte ) 검색을 지향
    • 추가로 별도의 index 생성 또는 필드 생성에 대한 고민 (_id 로 대체 가능)
  5. Index 도 Disk Size 가 할당되며,  해당 Field 에 대해 수정이 발생 시 마다 변경 되기에 무분별한 Index 생성 및 Size가 큰 Field 에 대한 생성은 지양
  6. 검색하는 목적에 맞는 Index 의  Type을 지정 (특별히, Text 또는 지도 상의 거리 등)
  7. 서브 다큐먼트 Field에 대해서는 인덱스 생성을 지양(인덱스 사이즈가 작아야 성능에 효율)
  8. 2중 배열은 지양 . 필요 시 업데이트 검색 등이 힘듦 -> 체크해 보자

 

[createIndex]

db.collection.createIndex(keys, options)

Index Name

Index Type

Parameter

Type

Memo

Non-Unique / Unique Index

Option

unique

Bollean

유일값 여부

{unique : true}

Single Field / Compound Index

 

 

 

단일 필드 또는 여러개의 필드를 이용하여 Index 를 생성

> Compound Index 생성 시 선행 필드가 중요하기에 Find / Update 진행 시 자주 사용하는 필드를 선행으로 지정 하면, 여러 쿼리에서 사용할 수 있기에 효율성이 증대

Multi Key Index

 

 

 

배열에 지정된 내용을 인덱스 하기 위함

배열의 모든 요소에 대해 개별의 인덱스 객체들을 자동 생성

> 명시적으로 멀티키 타입을 지정할 필요 없음

Background Index

(v4.2에서부터 해당 옵션은 사라지며, default 로 진행-index 생성 시 처음과 마지막에만 Lock)

Option

background

Bollean

Index 생성 시 많은 비용이 발생하여 성능 저하가 발생하는데, 적은 비용으로 백그라운드로 생성하여 DB에서 부하를 줄여 주는 방식

> 생성 진행되는 동안 background 로 생성하기에 메모리 체크가 필수

TTL Index

Option

expireAfterSeconds

Integer

  • 일정 시점이 지난 인덱스 데이터는 자동 삭제해 주는 기능
  • (지정한 시간동안만 Index 에서 Data가 존재하며, 이후에는 제거)
  • 제한시간을 설정하여 오래된 데이터를 삭제해 주는 기능

Sparse Index

Option

sparse

Bollean

Field 에서 Null 값을 가진 데이터가 대부분이고 드물게 어떠한 값을 가지고 있는 경우 생성하면 효율적

(인덱스의 크기가 줄며, 효율성을 올릴 수 있음 -> Null 값을 제거하고 Index 생성)

Partial Index (v3.2)

Option

partialFilterExpression

Document

Index 생성 시 해당 Field를 Filtering 한 결과를 생성

Ex ) 천만원 이상인 금액만 주로 Find하는 경우 인덱스 생성(해당 금액 이하는 Index 를 사용하지 못함)

db.emp.createIndex({salary:1},{partialFilterExpression:{salary:{$gte:10000000}}})

GeoSpatial(2d) Index

Option

bits

min

max

Integer

number

Number

공간인덱스

  • 공간내 거리나 좌표를 구할때 사용

지리 좌표 데이터의 효율적인 쿼리를 제공

  • 평면 기하학을 이용해 결과를 제공

GeoSpatial(2dsphere) Index

Option

2dsphereIndexVersion

Integer

지리 좌표 데이터의 효율적인 쿼리를 제공

  • 구체 기하학을 이용해 결과를 제공

GeoHayStack Index

Option

bucketSize

Number

 

Text Index

Option

 

 

 

weights

default_language

Language_override

textIndexVersion

document

String

String

Integer

하나의 Collection에 하나의 Text Index만 생성 가능

Hashed Index

 

 

 

  • Hash 기반의 샤딩을 제공하기 위해, Field 값을 Hash 하여 생성
  • Shard Cluster에서 데이터를 균등하게 분산하고자 할때 사용

Covered Index

 

 

 

여러개의 Field로 생성된  Compound Index 에서 검색할 때 Index 검색 만으로도 조건을 만족하는 Document 를 추출이 가능한 경우

.explain() 확인 시 [...indexOnly:true]를 확인할 수 있음

Wildcard index (v4.2)

 

wildcardProjection

document

https://docs.mongodb.com/manual/core/index-wildcard/#wildcard-index-core

아래 옵션은 사용 할 수 없음

* Compound

* TTL

* Text

* 2d (Geospatial)

* 2dsphere (Geospatial)

* Hashed

* Unique

collation (v3.4)

Option

collation

Document

주로 강세등이 있는 언어들에 대해서 binary 화 한 후에 비교(French 등)

* text indexes,

* 2d indexes, and

* geoHaystack indexes.

 

만약 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 기능을 사용해야함
    • 참고 : https://sarc.io/index.php/nosql/1769-mongodb-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" } )
  • text Index를 여러개 생성 시 오류
    • month_data 로 이미 생성 했는데, 추가로 생성 시 오류

  • 가중치 추가하여 진행 ($meta)
    • "아앙아" 라는 문자내에서 "아"를 검색하게 되면 가중치는 2가 됨 (아 *2개)
    • > db.array.find({$text:{$search:"서울"}},{score:{$meta: "textScore"}}).sort({score:{$meta:"textScore"}}).pretty()
    • 텍스트 내에 값을 찾으면 그 찾고자 하는 값의 개수에 곱하기가 되어 계산
    • 참고 : https://sarc.io/index.php/nosql/1769-mongodb-text-index
 

MongoDB Text index

[{"id":"10","listid":"1","parentid":"0","videosource":"youtube","videoid":"KiwjxNKXfxY","imageurl":"https:\/\/i.ytimg.com\/vi\/KiwjxNKXfxY\/default.jpg,120,90;https:\/\/i.ytimg.com\/vi\/KiwjxNKXfxY\/mqdefault.jpg,320,180;https:\/\/i.ytimg.com\/vi\/KiwjxNKX

sarc.io

[ Wildcard Indexes ]

  • 필드 하위에 $**를 붙여서 이 필드의 하위 모든 문서에 와일드카드 익덱스를 만드는 것
  • 필드 하위 필드들을 한번씩 Scan 각각의 인덱스를 만드는것
    • 문서/배열로 재귀하여 모든 필드에 대한 값을 저장
  • All fields on Index
    • 각 Document에 대한 모든 Field 를 인덱싱
    • _id 필드를 생략
  • wildcardProjection
    • wildcard 사용시 특정 필드 경로를 포함하거나 제외할 수 있는 옵션.
    • 모든 색인을 작성하는 경우에만 유효
  • Indexing은 추가로 발견되는 포함된 문서를 계속 탐색

 

#Wildcard Index / attributes 필드의 하위 document에 인덱스생성

db.collection.createIndex({ "attributes.$**": 1 })

 

# All fields on Index

db.collection.createIndex( { "$**" : 1 } )

 

#Wildcard Text Index

db.collection.createIndex( { "$**": "text" } )

[ 2dsphere Indexes ] 

[ 2d Indexes ]

[ geoHaystack Indexes ]

[ Hashed Indexes ]

[ Index Properties ]

[ Index Builds on Populated Collections ]

[ Index Intersection ]

  • 2개의 각기 다른 Field를 가진 Index들이 하나의 쿼리에 대해 인덱스를 이용(하나의 쿼리에 2개의 인덱스가 사용)
  • Equal + Equal로 이루어진 쿼리 의 Index의 경우 AND_SORTED 스테이지가 사용
  • Equal + Range로 이루어진 쿼리의 Index의 경우 AND_HASHED 스테이지가 사용
  • Index Intersection이 다른 방법보다 효율적이거나 최신의 알고리즘이 아니기에, 효율적인 최적화가 아니다.
  • (Index Intersection을 사용한다는 것은 Index가 잘못 설계[각 Filed마다 Single Filed로 인덱스가 여러개 생성] 되어 어쩔수 없이 사용되어지는 방법이기에 인덱스 설계를 다시 고민해야 한다)
  • 인덱스 인터섹션 최적화가 사용되는 경우는 어떤 인덱스로도 최적화하기가 어렵다고 판단되는 경우 사용

[ Manage Indexes ]

[ Measure Index Use ]

[Indexing Strategies ]

[ Indexing Reference ]

 

[getIndexes()]

  • Collection 의 Index 정보 가져오기 : db.collection.getIndexes()
  • listIndexes 라는 권한이 필요 (read role 있으면 가능)

 

[ Index 사용통계 ]

  • Index 사용 통계 
  • db.monsters.aggregate([{ $indexStats: {} }]).pretty()
  • Ops : 0 이므로 한번도 _id 로 검색을 하지 않음

 

[ explain() ]

  • Explain  확인
  • executionStats 모드
    • 인덱스 사용 여부
    • 스캔한 문서들의 수
    • 쿼리의 수행 시간
  • allPlansExecution 모드
    • 쿼리 계획을 선택하는데 필요한 부분적인 실행 통계
    • 쿼리 계획을 선택하게 된 이유

 

 

[ Background Index 생성 ]

  • 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를 통해 세컨더리에 생성 되었는지 확인 하면 됨
반응형

+ Recent posts