ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Index
    Database/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 속성

    1. 대소문자를 구분에 대한 설정을 할 수 있습니다. Collection 생성시 혹은 Index 생성시 locale 과 strength 를 설정해야합니다. (case insensitive)
    2. 유일속성을 지정할 수 있습니다. (unique) 이를 설정할 경우 중복값을 포함한 데이터는 무시합니다.
    3. 부분적인 데이터에 적용할 인덱스를 생성할 수 있습니다. (partialFilterExpression)
    4. Date 타입과 관련된 정보는 만료지정을 통해 일정시간이후 자동 삭제처리할 수 있습니다. 단 만료 삭제는 60초 단위의 쓰레드에서 삭제함에 따라서 설정시각과 정확하게 맞아 떨어지진 않습니다. (TTL Index)
    5. 숨김처리를 할 수 있습니다. (hidden) 이를 설정할 경우 Index 삭제시의 영향도에 대하여 평가 할 수 있습니다.
    6. 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 종류

    1. _id
      • 기본 인덱스로 Collection 생성시 별도의 Index 필드를 지정하지 않을 경우 자동으로 _id 필드 값을 ObjectId로 설정해줍니다.
      • 해당 필드는 삭제할 수 없습니다.
      • 해당 인덱스는 분산처리시 시스템적으로 사용됩니다.
    2. Single
      • 단일 필드 인덱스로 하나의 필드값에 대해서 오름차순, 내림차순을 설정합니다.
      • 최소값이나 최대값부터 순회할 수 있음으로 오름차순, 내림차순은 중요하지 않습니다.

    Single Index Exam

     

    1. 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

     

    1. Multikey
      • 필드 타입이 배열인 필드에 인덱스를 적용할때 사용합니다. (JsonArray 내에서 Indexing)

    multikey index exam

     

    1. Geospatial
      • GPS 좌표를 기준으로 Index를 설정할 수 있습니다. loc 혹은 locs 에 2d, 2dsphere를 설정함으로써 적용합니다.
    2. Text
      • 문자열을 기준으로 Index를 설정합니다. 어떠한 단어도 무관하며, TextIndex 버전에 따라서 동작이 일부 달라질 수 있습니다.
      • Text Index 는 단순 이진비교만 지원하고 정렬에 대한 지원은 하지 않습니다.
      • 분음부호에 대한 구분을 하지 않습니다.
    3. Hashed
      • B-Tree 가 아닌 Hash 구조를 사용한 검색 구조를 만들 경우 사용합니다. 내부정렬은 하지 않습니다.

     

    기본 동작 방식

    1. Collection 에 index를 지정할 경우 MongoDB 에서는 Index 를 기준으로 B-Tree 를 구성
    2. 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
Designed by Tistory.