Index

  • 디비의 검색을 빠르게 하기 위하여 미리 데이터의 순서를 정리해두는 과정
  • MongoDB는 고정된 스키마는 없지만 원하는 데이터 필드를 인덱스로 지정하여 검색결과를 빠르게 하는것이 가능
  • NOSQL 에서도 index를 잘 설계해야 최대의 효율이 가능
  • MongoDB를 효율적으로 사용하고 하드웨어의 성능을 최대로 끌어내려면 index 종류와 사용 방법에 대한 이해 필요
  • MongoDB는 B트리 구조로 index를 구현
  • 고유 index, 최소 index, 다중 키 index 지원
  • 복합 index, 단일 index 지원

Index 개념

  • 도큐먼트를 쿼리해오기 위한 작업량을 줄임
    • 적당한 인덱스가 없으면 질의 조건을 만족할 때까지 모든 도큐면트를 순차적으로 스캔
  • 한 쿼리당 하나의 index만 유효
  • 두 개의 index가 필요하다면, 복합 index 사용
    • a,b 필드로 구성된 복합 index를 가지고 있다면 a에 대해 단일 index는 제거 가능
    • 복합 index에서 키의 순서 매우 중요
  • _id는 기본적으로 생성되는 index로 도큐먼트를 가르키는 유일한 키값으로 사용
    도큐먼트에 빠르게 접근하기 위해 각 _id는 index로 관리됨

Index 효율

  • 쿼리 성능 향상을 위해 무한히 index를 추가하는 것은 불가능
  • 모든 index에는 결국 유지비가 소요됨
  • 어떤 데이터가 도큐먼트에 추가되거나 수정될 때 마다 그 컬렉션에 대해 생성된 index도 그 새로운 도큐먼트를 포함시키도록 수정되어야 함
  • 최악의 경우에는 결국 데이터를 다시 정렬해야 하는 상황 발생
  • index는 읽기 위주의 어플리케이션에서 유용
  • 읽기보다 쓰기 작업이 많다면 어느정도 index를 포기하거나 index를 위한 컬렉션을 따로 운영해야 함
  • MongoDB는 기동 시, 모든 데이터 파일을 메모리에 매핑함
  • 모든 도큐먼트, 컬렉션, 인덱스를 포함하는 데이터 파일이 페이지 라고 부르는 4kb 정도의 청크 단위로 운영체제에 의해 램에 적재됨
  • 램의 모든 데이터를 수용만 할 수있다면 디스크 액세스 횟수 최소화가 가능
  • 모든 데이터를 수용하지 못하면 페이지 폴트가 자주 발생하게 되고 운영체제가 디스크를 빈번하게 액세스하게 됨으로 읽기/쓰기 연산 지연 발생
  • 스래싱(thrashing) : 모든 데이터를 디스크에서 액세스 해야하는 경우 굉장한 성능저하를 초래함
  • 최소한의 인덱스가 메모리에 위치할 수 있도록 최소화될 필요가 있음
  • 복합 인덱스는 더 많은 공간을 필요로함을 고려해야 함

B트리

  • MongoDB는 내부적으로 B-Tree 알고리즘을 이용하여 인덱스를 구성
  • B-Tree는 1970년대 후반부터 데이터베이스의 레코드와 인덱스로 활발하게 사용되고 있음
  • 트리구조와 유사한 데이터 구조
  • 트리에서 각 노드는 여러 개의 키를 갖는 것이 가능
  • MongoDB에서 사용하는 B-Tree는 새 노드에 대해 8,192 바이트를 할당함
    (= 각 노드가 수백 개의 키를 가질 수 있음을 의미)
  • 인덱스의 평균 크기에 따라 달라질 수도 있지만,
    보통 키의 평균적인 크기는 30바이트 안팎

B트리의 데이터베이스 인덱스에 적합한 두 가지 특징

  • 정확한 일치, 범위 조건, 정렬, 프리픽스 일치 등 다양한 쿼리를 용이하게 처리하도록 도와줌
  • 키가 추가되거나 삭제되더라도 밸런스 유지

MongoDB Index

인덱스 확인

  • db.컬렉션.getIndexes()


인덱스 생성

  • db.컬렉션.createIndex( {"name":1} ) - 오름차순 1, 내림차순 -1


인덱스 생성 - 백그라운드 옵션

  • 컬렉션 내 데이터가 많을 경우 인덱스 생성으로 인한 비용을 줄이기 위해 사용
  • db.컬렉션.createIndex( {"name":1}, {background:true} )


인덱스 생성 - 고유 인덱스

  • db.컬렉션.createIndex( {"name":1}, {unique:true} )
  • unique 속성을 지정하여 중복 데이터가 저장되지 못하도록 하면, 데이터 저장과 검색속도를 늘리는데 도움이 됨


인덱스 삭제  - 특정 필드

  • db.컬렉션.dropIndex( {"name":1});


인덱스 삭제  - 모든 인덱스

  • db.컬렉션.dropIndexs();


인덱스 유무에 따른 검색 속도 비교

1백만 건의 문서를 가지는 컬렉션 생성

for (i=0; i<1000000; i++) {
  db.users.insert (
    {
    "i" : i,
    "username" : "user" + i,
    "age" : Math.floor(Math.random()*120),
    "created" : new Date()
    }
  );
}

특정 사용자 정보를 가진 문서를 찾기

  • db.users.find({username:"user101"}).explain()
  • 인덱스가 존재하지 않으므로 풀스캔 / 721 millis

인덱스 생성

  • db.users.createIndex("username":1})
  • 인덱스가 존재 / 3millis


인덱스 사용 시 주의점

  • 인덱스를 사용하면 쿼리 수행 시간이 단축됨
  • 모든 쓰기 ( 읽기, 갱신, 삭제 ) 작업은 인덱스 때문에 더 오래 걸린다.
  • 데이터가 변경될 때 마다 문서 자체는 물론이고 몽고디비에서 모든 인덱스를 갱신한다.
  • 몽고디비는 컬렉션당 최대 64개의 인덱스를 가지도록 제한된다.
  • 일반적으로 컬렉션에 2-3개 이상의 인덱스를 가지지 않는 것이 좋다.
  • 몽고디비 인덱스는 전형적인 관계형 데이터베이스의 인덱스와 거의 흡사하게 작동된다.
  • 새로운 인덱스를 구축하려면 오랜 시간이 걸리고 자원을 많이 먹는다.
  • 몽고디비는 인덱스 구축이 완료될 때 까지 데이터베이스의 모든 읽기와 쓰기를 중단하며 구축한다.
  • background 옵션은 사용하여 인덱스를 구축하면 다른 작업이 가능하기는 하지만 효율성이 떨어지고 포그라운드 인덱싱보다 훨씬 느리다.

 

 

 

+ Recent posts