1. Index
1.1 index 기본 개념
- DB 의 검색을 빠르게 하기 위해 미리 데이터의 순서를 정리해두는 과정
- MongoDB 는 **고정된 스키마는 없지만 원하는 데이터 필드를 인덱스로 지정하여 검색결과를 빠르게 하는것이 가능**
- NOSQL 에서도 index 를 잘 설계해야 최대의 효율이 가능
- MongoDB 를 효율적으로 사용하고 하드웨어의 성능을 최대로 끌어내려면 index 의 종류와 사용 방법에 이해 필요
- MongoDB 는 B트리 구조로 index 를 구현
- 고유 index, 희소 index, 다중 키 index 지원
- 복합 index, 단일 index 지원
- index 는 도큐먼트를 쿼리해오기 위한 작업량을 줄임
- 적당한 index 가 없으면 질의 조건을 만족할 때까지 모든 도큐먼트를 순차적으로 스캔
- 한 쿼리당 하나의 index 만 유효
- 두 개의 index 가 필요하다면 복합 index 를 사용
- a와 b 필드로 구성된 복한 index 를 가지고 있다면 a 에 대해 단일 index 는 제거해도됨
- 복합 index 에서 키의 순서는 매우 중요
- _id는 기본적으로 생성되는 index 로 도큐먼트를 가르키는 유일한 키값으로 사용(도큐먼트에 빠르게 접근하기 위해서 각 _id 는 index 로 관리 됨)
1.2 index 효율
- 쿼리 성능 향상을 위해 무한히 index 를 추가하는 것은 불가능
- 모든 index 에는 결국 유지비가 소요됨
- 어떤 데이터가 도큐먼트에 추가되거나 수정될 때마다 그 컬렉션에 대해 생성된 index 도 그 새로운 도큐먼트를 포함시키도록 수정되어야 함
- 최악의 경우에는 결국 데이터를 다시 정렬해야 하는 상황 발생
- index 는 읽기 위주의 어플리케이션에서 유용
- 읽기보다 쓰기 작업이 많다면 어느 정도 index 를 포기하거나 index 를 위한 컬렉션을 따로 운영해야 함
- MongoDB 는 기동시 모든 데이터 파일을 메모리에 매핑함
- 모든 도큐먼트, 컬렉션, 인덱스를 포함하는 모든 데이터 파일이 페이지(page)라고 부르는 4kb 정도의 청크 단위로 운영체제에 의해 램에 적재
- 램의 모든 데이터를 수용만 할 수 있다면 디스크 액세스 횟수 최소화 가능
- 모든 데이터를 수용하지 못하면 페이지 폴트가 자주 발생하게 되고 운영체제가 디스크를 빈번하게 액세스하게 됨으로 인해 읽기/쓰기 연산 지연 발생
- 스래싱(thrashing) : 모든 데이터를 디스크에서 액세스 해야 하는 경우 굉장한 성능 저하를 초래
- 최소한의 인덱스가 메모리에 위치 할 수 있도록 최소화 될 필요가 있음
- 복합 인덱스는 더 많은 공간을 필요로 함을 고려해야 함
1.3 B트리
- MongoDB 는 내부적으로 B트리(B-Tree) 알고리즘을 이용하여 인덱스 구성
- B트리는 1970년대 후반부터 데이터베이스의 레코드와 인덱스로 활발하게 사용되고 있음
- B트리의 데이터베이스 인덱스에 적합한 두 가지 특징
- 정확한 일치, 범위 조건, 정렬, 피리픽스일치 등 다양한 쿼리를 용이하게 처리하도록 도와준다는 점
- 키가 추가되거나 삭제되더라도 밸런스 유지한다는 점
- B트리는 트리구조와 유사한 데이터 구조
- 트리에서 각 노드는 여러 개의 키를 갖는 것이 가능
- MongoDB 에서 사용하는 B트리는 새 노드에 대해 8,192 바이트를 할당함(각 노드가 수백 개의 키를 가질수 있음을 의미)
- 인덱스키의 평균 크기에 따라 달라질 수도 있는데, 보통 키의 평균적인 크기는 30바이트 안팎임
2. MongoDB Index 사용
2.1 인덱스 확인
db.person.getIndexes()
2.2 인덱스 생성
- 기존에 기본으로 들어있는 _id 이외에 index 를 생성합니다.
- 오름차순이면 1, 내림차순이면 -1 을 지정
db.person.ensureIndex({"name":1})
- 인덱스 생성 시 많은 시간이 걸릴 수 있으니 백그라운드 옵션을 사용할 수 있습니다.
db.person.ensureIndex({"name" : 1}, {background : true})
- 만일 고유한 인덱스를 생성하고 싶다면 **unique** 옵션을 사용하여 index 를 생성합니다.
- **unique** 속성을 지정해서 중복 데이터가 저장되지 못하도록 하면, 데이터 저장과 검색 속도를 늘리는데 도움이 됨
db.person.ensureIndex({"name" : 1}, {unique : true})
- 특정 필드를 unique 하게 했을때 기존에 이미 중복된 데이터가 있을 경우에 **dropDups** 를 이용하면 중복되는 데이터 삭제하고 인덱스 저장 가능
db.person.ensureIndex({"name" : 1}, {unique : true, dropDups : true})
2.3 인덱스 삭제
db.person.dropIndex({"name" : 1});
- 해당 컬렉션 안에 있는 모든 index 를 삭제합니다.(_id 는 제외)
db.person.dropIndexes();