-
IndexDatabase/MongoDB 2023. 2. 2. 22:35
검색에 대한 속도 개선을 위해 활용합니다. (find, sort 등)
Index 는 1 로 설정할 경우 오름차순, -1 로 설정할 경우 내림차순으로 내부정렬합니다.
Index는 한 쿼리에 한 index만 유효합니다. 따라서 두 개의 index 가 필요하다면 복합 index를 사용합니다.
Index는 어떤 데이터가 도큐먼트에 추가되거나 수정될 때( write 작업 ) 그 컬렉션에 생성되어 있는 index도 새로운 도큐먼트를 포함시켜 수정됩니다.
이로 인하여 index 추가 시 wirte 작업은 느려질 수 있습니다. 따라서 index는 read 작업 위주의 애플리케션에서 유용하고 읽기보다 쓰기 작업이 많으면 index를 추가하는 것은 고려해야 합니다.일반 검색결과에 대해서 정렬해 주는기능이 아닌 내부적으로 관리됩니다.
Index 생성예시
db.book.createIndex({name:1})
- single field index : 단일 key 인덱스, 1은 오름차순, -1은 내림차순
db.book.createIndex({name:1, hits:-1})
- compound(복합) field index : 복합적으로 key index
db.book.createIndex({name:1},{unique:true})
- 유일속성을 지정
db.book.createIndex({name:1,hits:-1},{partialFilterExpression:{hits:{$gte:100}}})
- hits가 100 이상인 field에만 인덱스를 적용
db.book.getIndexes()
- index 조회
db.book.dropIndex({name:1})
- name에 건 인덱스를 제거
Index 속성
- 대소문자를 구분에 대한 설정을 할 수 있습니다. Collection 생성시 혹은 Index 생성시 locale 과 strength 를 설정해야합니다. (case insensitive)
- 유일속성을 지정할 수 있습니다. (unique) 이를 설정할 경우 중복값을 포함한 데이터는 무시합니다.
- 부분적인 데이터에 적용할 인덱스를 생성할 수 있습니다. (partialFilterExpression)
- Date 타입과 관련된 정보는 만료지정을 통해 일정시간이후 자동 삭제처리할 수 있습니다. 단 만료 삭제는 60초 단위의 쓰레드에서 삭제함에 따라서 설정시각과 정확하게 맞아 떨어지진 않습니다. (TTL Index)
- 숨김처리를 할 수 있습니다. (hidden) 이를 설정할 경우 Index 삭제시의 영향도에 대하여 평가 할 수 있습니다.
- exist를 명시적으로 적시하지 않는 경우 검색에 대한 결과가 부정확할 수 있습니다. 이에 따라서 sparse 속성을 지정함에 따라서 정확한 결과를 도출해낼 수 있습니다. ( 1.모든 Document 가 Index Key 를 가지고 있지 않는 경우 2. partialFilterExpression 옵션과 같이 사용할 수 없습니다. )
> db.book.find() { "_id" : ObjectId("606d143ded469e92c204ac31"), "name" : "A", "hits" : 100, "auther" : [ { "name" : "park" }, { "name" : "lee" } ] } { "_id" : ObjectId("606d143ded469e92c204ac32"), "name" : "B", "hits" : 50, "auther" : [ { "name" : "kim" } ] } { "_id" : ObjectId("606d1474ed469e92c204ac33"), "name" : "C", "hits" : 30, "auther" : [ { "name" : "kim" }, { "name" : "choi" } ] } { "_id" : ObjectId("606e4b8b41b02ac25c437a9b"), "name" : "DD" } > db.book.createIndex({hits:1}, {sparse:false}) > db.book.find().hint({hits:1}).count() 4 > db.book.dropIndex({hits:1}) > db.book.createIndex({hits:1}, {sparse:true}) > db.book.find().hint({hits:1}).count() 3
Index 종류
- _id
- 기본 인덱스로 Collection 생성시 별도의 Index 필드를 지정하지 않을 경우 자동으로 _id 필드 값을 ObjectId로 설정해줍니다.
- 해당 필드는 삭제할 수 없습니다.
- 해당 인덱스는 분산처리시 시스템적으로 사용됩니다.
- Single
- 단일 필드 인덱스로 하나의 필드값에 대해서 오름차순, 내림차순을 설정합니다.
- 최소값이나 최대값부터 순회할 수 있음으로 오름차순, 내림차순은 중요하지 않습니다.
Single Index Exam - Compound
- 두개 이상의 필드를 인덱스로 사용하는 복합 인덱스라고 부릅니다.
- a-b 순으로 키를 설정할 경우, b-a 에 대한 정렬은 지원하지 않습니다. 따라서 a-b로 지정할 경우 검색시 조건을 a-b 순으로 지정해야합니다.
- 복합 인덱스의 경우 a-b-c-d 를 키로 지정할 경우, (a, a-b, a-b-c) 를 키로 지정한 것은 무시되며 부분에 대한 검색쿼리 또한 지원합니다.
- 복합 인덱스는 부분에 대한 검색쿼리를 할 경우 순서대로만 조건지정할 수 있습니다. 예로 a-b-c-d 인덱스인 경우, b-c 와 같은 조건은 불가합니다.
- Sort 의 경우 위의 언급된 순차적인 조건지정은 무시됩니다. (ex. db.data.find( { b: 5, a: 3 } ).sort( { c: 1 } ))
- 생성된 인덱스: { a: 1, b: -1 } - 지원하는 조회 쿼리: { a: 1, b: -1 } - 지원하는 조회 쿼리: { a: -1, b: 1 } - 지원하지 않는 조회 쿼리: { b: 1, a: 1 } - 지원하지 않는 조회 쿼리: { b: -1, a: -1 }
compound index exam - Multikey
- 필드 타입이 배열인 필드에 인덱스를 적용할때 사용합니다. (JsonArray 내에서 Indexing)
multikey index exam - Geospatial
- GPS 좌표를 기준으로 Index를 설정할 수 있습니다. loc 혹은 locs 에 2d, 2dsphere를 설정함으로써 적용합니다.
- Text
- 문자열을 기준으로 Index를 설정합니다. 어떠한 단어도 무관하며, TextIndex 버전에 따라서 동작이 일부 달라질 수 있습니다.
- Text Index 는 단순 이진비교만 지원하고 정렬에 대한 지원은 하지 않습니다.
- 분음부호에 대한 구분을 하지 않습니다.
- Hashed
- B-Tree 가 아닌 Hash 구조를 사용한 검색 구조를 만들 경우 사용합니다. 내부정렬은 하지 않습니다.
기본 동작 방식
- Collection 에 index를 지정할 경우 MongoDB 에서는 Index 를 기준으로 B-Tree 를 구성
- Index 로 검색이 호출되는 경우 B-Tree 에서 Banlanced Binary Search 를 통한 검색이 진행
Indexing 속도 측정
생성한 index가 문제가 없는지 확인하기 위해서 index를 측정해야 합니다. 아래 3가지 명령어로 이를 확인하고 문제 있는 index는 수정해야 합니다.
$indexStats: index 통계
> db.test.createIndex({score:1}) > db.test.find({score:53}) > db.test.aggregate( [ { $indexStats: { } } ] ) //결과 중 accesses 필드를 확인하면 since 시간 이후로 몇 번 해당 index를 사용했는지 확인할 수 있습니다 , 결과 중 name 은 Index명을 의미합니다. // 특정 shard 로 accesses 가 과하게 몰린다면 index를 수정할 필요성이 있습니다. { "name" : "_id_", "key" : { "_id" : 1 }, "host" : "db1:27017", "accesses" : { "ops" : NumberLong(3), "since" : ISODate("2021-05-10T05:04:56.502Z") }, "shard" : "rs0", "spec" : { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } } { "name" : "_id_", "key" : { "_id" : 1 }, "host" : "db1:27018", "accesses" : { "ops" : NumberLong(0), "since" : ISODate("2021-05-10T05:05:02.615Z") }, "shard" : "rs1", "spec" : { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } }
explain()
특정 퀴리의 수행 통계
이는 특정 쿼리 수행 통계를 알 수 있습니다. 자세한 내용은 문서에서 확인 가능합니다.queryPlanner: 가장 효율적인 쿼리를 찾기 위해 쿼리 최적화를 제공합니다.
executionStats mode: 특정 질의에서 실제로 실행한 결과의 세부사항을 제공합니다.
allPlansExecution mode: queryPlanner + executionStats 내용 모두 포함hint()
특정 인덱스 테스트
이는 테스트하고 싶은 특정 인덱스가 원하는 쿼리에 효과 있는지 알아보기 위해 사용합니다.아래 예제는 score 조건으로 조회하지만 _id 인덱스를 사용하는 경우를 hint()로 테스트하며 explain으로 총 시간을 확인하는 명령어입니다.
db.user.find({score:53}).hint({_id:1}).explain("executionStats").executionStats.executionTimeMillis
참조 : https://docs.mongodb.com/manual/indexes/
참조 : https://docs.mongodb.com/manual/reference/method/cursor.explain/'Database > MongoDB' 카테고리의 다른 글
Sharding & Cluster (1) 2023.02.02 View (0) 2023.02.02 MapReduce (0) 2023.02.02 Operator & Function (0) 2023.02.01 Aggregate (0) 2023.02.01