Notepad
Published 2021. 12. 23. 13:34
MongoDB - 인덱스1 dev/DB

8. 인덱싱과 쿼리 최적화

8.1 인덱싱의 이론적 고찰

  • 책의 목차와 같이 찾고자 하는 데이터를 빠르게 찾기 위한 것
  • 단순 인덱스
    • 단일 키에 대해 생성한 인덱스
  • 복합 인덱스
    • 둘 이상의 키를 사용하여 생성한 인덱스
    • 키 순서 중요
  • 인덱스 효율
    • 인덱스에는 비용이 발생하니 조심히 생성
      • 삽입 연산을 수행할 때 마다 새 도큐먼트가 인덱스가 포함되도록 수정

8.2 인덱싱의 실제

8.2.1 인덱스 타입

  • 인덱스에 B-트리 인덱스가 사용되며 몇가지 특성을 적용할 수 있음
  • 고유 인덱스
    • 필드의 해당 도큐먼트에 고유한 키임을 보장하기 위해 사용
    • unique 옵션을 지정해서 사용
      // 고유 인덱스 생성
      db.users.createIndex({ username: 1}, { unique: true });
  • 희소 인덱스
    • null이 아닌 값에 대해 고유 인덱스를 설정하려고 할때 사용
    • sparse 옵션 추가
      db.products.createIndex({ sku: 1}, { unique: true, sparse: true });
  • 다중키 인덱스
    • 필드의 값이 배열인 경우 사용 가능한 인덱스
      {
          name: "Wheelbarrow",
          tags: ["tools", "gardening", "soil"]
      }
  • 해시 인덱스
    • 해시된 값이 순서를 결정
    • 해시를 인덱스 정렬 방향으로 전달하여 생성
      // 해시 인덱스 추가
      db.recipes.createIndex({recipe_name: 'hashed'});
    • 제한 사항
      • 동등 쿼리는 거의 동이랗게 작동하지만 범위 쿼리는 지원 X
      • 다중 키 해시 인덱스는 허용 X
      • 부동 소수점 값은 해시되기 전에 정수로 변환
  • 지리공간적 인덱스
    • 지구의 곡률을 포함하여 지리적 거리를 효율적으로 계산할 수 있는 인덱스

8.2.2 인덱스 관리

  • 인덱스 생성과 삭제

    • 생성

      // createIndex 호출로 생성
      // 헬퍼 메서드도 동일한 적업 시행
      use green;
      spec = {ns: "green.users", key: {'addresses.zip': 1}, name: 'zip'};
      // 인덱스 생성
      db.system.indexes.insert(spec, true);
      
      // 인덱스 확인
      db.system.indexes.find().pretty();
      {
          "ns" : "green.users",
          "key" : {
              "addresses.zip" : 1
          },
          "name" : "zip",
          "v" : 1
      }
    • 삭제

      • system.indexes에 직접 인덱스 도큐먼트 삭제 연산은 금지되어 있음
      • deleteIndexes를 수행해서 인덱스 삭제 가능
        use green;
        db.runCommand({deleteIndexes: "users", index: "zip"});
        

      use green;
      db.users.dropIndex("zip_1");
      ```

    • 인덱스 구축

      • currentOP(): 인덱스 빌드 과정 확인
        > db.currentOp()
        {
          "inprog" : [
              {
                  "opid" : 83695, // 연산ID
                  "active" : true,
                  "secs_running" : 55,
                  "op" : "insert",
                  "ns" : "stocks.system.indexes", // 쿼리상에서 인덱스 사용 확인
                  "insert" : {                    // stock 데이터베이스
                      "v" : 1,
                      "key" : {
                          "desc" : 1
                      },
                      "ns" : "stocks.values",
                      "name" : "desc_1"
                  },
                  "client" : "127.0.0.1:56391",
                  "desc" : "conn12",
                  "threadId" : "0x10f20c000",
                  "connectionId" : 12,
                  "locks" : {                     // 연산과 관련된 잠금
                      "^" : "w",
                      "^stocks" : "W"
                  },
                  "waitingForLock" : false,
                  "msg" : "index: (1/3) external sort Index: (1/3)
                  External Sort Progress: 3999999/4308303 92%",
                  "progress" : {
                      "done" : 3999999,
                      "total" : 4308303
                  },
                  "numYields" : 0,
                  "lockStats" : {
                      "timeLockedMicros" : {},
                      "timeAcquiringMicros" : {
                          "r" : NumberLong(0),
                          "w" : NumberLong(723)
                      }
                  }
              }
          ]
        }
      • 인덱스가 생성되는 동안에는 데이터베이스에 읽거나 쓰기를 할 수 없음
      • Lock에 대한 해결법
        • 백그라운드 인덱싱
          • 쓰기 잠금은 되지만 데이터베이스에 대한 다른 읽기나 쓰기를 허용하기 위해 잠시 멈춤
          • 인덱스 선언 시 backgorund 옵션 추가
            db.values.createIndex({open: 1, close: 1}, {background: true});
        • 오프라인 인덱싱
          • 일반적으로 복제 노드를 오프라인 상태로 변경
          • 인덱스를 구축한 다음 마스터 노드로부터 업데이트
          • 업데이트 완료 후 이 노드를 프라이머리 노드로 변경
          • 다른 세컨더리 노드들도 오프라인 상태로 바꾼 후 각자 인덱스 구축
      • 단편화 제거(DEFRAGMENTING)
        • 대량의 데이터 삭제가 자주 발생한다면 인덱스가 심하게 단편화됨
        • 심하게 단편화가 되었을 때 인덱스 재구축 고려해 볼 수 있음
        • reIndex 명령어 수행으로 인덱스 재구축
          db.values.reIndex();
        • 재구축 동안 쓰기 잠금을 하므로 MongoDB를 일시적으로 사용 X

출처

  • MongoDB in Action 2nd

'dev > DB' 카테고리의 다른 글

이력관리  (0) 2022.03.22
MongoDB - 업데이트, 원자적 연산, 삭제  (0) 2021.11.11
MongoDB - 집계2  (0) 2021.11.04
MongoDB - 집계1  (0) 2021.10.28
MongoDB - Query Selectors(1)  (0) 2021.10.22
profile

Notepad

@Apio

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!