반응형

Single Field Index(단일 필드 인덱스)

 하나의 필드 인덱스를 사용하는 것을 단일 필드 인덱스라고 합니다. MongoDB에는 기본적으로 컬렉션에 _id라는 단일 필드 인덱스가 생성됩니다.

단일 필드 추가 방법은 아래와 같습니다. 원하는 feild를 입력합니다. 단일 필드 인덱스에서는 1은 오름차순 -1은 내림차순을 의미합니다. 하지만 단일 필드 인덱스에서는 오름차순인지 내림차순인지 중요하지 않습니다. 왜냐하면 어떤 방향으로 가도 동일하게 접근하기 때문입니다.

> db.user.createIndex({score:1})

아래 그림은 score에 인덱스를 주어 score 크기대로 오름차순(숫자 1이 오름차순, 숫자 -1은 내림차순입니다.) 정렬된 것을 확인할 수 있습니다.

https://docs.mongodb.com/manual/indexes/ 그림

인덱스 유무 속도 비교

 인덱스 생성 전과 인덱스 생성 시 속도 비교해봅니다. 아래와 같은 explain 명령어를 사용해서 실행 속도를 파악해 봅니다. 저는 아래 명령어 입력 시 764밀리 초로 0.764초 정도 나왔습니다.

>db.user.find({score:"23"}).explain("executionStats").executionStats.executionTimeMillis

764

 그러면 이제 score에 대한 인덱스를 생성합니다.

> db.user.createIndex({score:1})

 인덱스 생성 후, 실행 속도를 확인해 봅니다. 저는 0이라는 값이 나왔습니다. 실습을 통해 인덱스로 매우 빠른 검색이 가능하다는 것을 알 수 있었습니다.

> db.user.find({score:"56"}).explain("executionStats").executionStats.executionTimeMillis

0

 

 

Compound Index(복합 인덱스)

 두 개 이상의 필드를 사용하는 인덱스를 복합 인덱스라고 부릅니다.

아래와 같이 인덱스를 생성한다면, 아래 그림과 같이 userid는 오름차순으로 정렬됩니다. 그리고 같은 userid를 지니면 score로 내림차순 정렬하게 됩니다. 예를 들면 동일한 userid 인"ca2"는 score가 내림차순으로 정렬되어 있음을 그림에서 확인할 수 있습니다.

> db.user.createIndex({userid:1 ,score:-1})

 

https://docs.mongodb.com/manual/core/index-compound/ 그림

 복합 인덱스를 사용할 때는 아래의 특징을 고려하며 생성합시다. 이는 MongoDB 문서에서 확인할 수 있습니다.

- 특징 1. sort 연산 시 인덱스 순서를 고려하여 생성하자.

 복합 인덱스에서는 키의 순서가 매우 중요합니다. 만일 복합 인덱스에서 순서가 userid-score가 아니라 score-userid로 생성하는 것은 다른 인덱스를 생성한 것입니다.

정렬 시 인덱스 순서와 조회 시 순서가 동일해야 합니다. 예를 들어 아래와 같이 인덱스 a-b순서로 생성하면 a-b 정렬은 지원을 하지만, b-a로 정렬은 지원하지 않습니다.

 

- 특징 2. 단일 인덱스와 다르게 복합 인덱스는 정렬 방향을 고려하자.

 검색 쿼리에서 복합 인덱스를 사용하는 경우 지정된 정렬 방향은 index와 일치해야 합니다. 예를 들어 아래와 같이 두 필드 정렬이 역으로 생성된 경우라면 역으로 조회하는 쿼리는 지원하지만, 동일한 정렬을 하는 쿼리는 지원하지 않습니다.

- 생성된 인덱스: { a: 1, b: -1 }

- 지원하는 조회 쿼리: { a: 1, b: -1 }
- 지원하는 조회 쿼리: { a: -1, b: 1 }

- 지원하지 않는 조회 쿼리: { b: 1, a: 1 }
- 지원하지 않는 조회 쿼리: { b: -1, a: -1 }

 아래 예제로 실습을 진행해 봅시다. 이전에 생성한 인덱스는 drop 하고 진행해 봅니다. {userid:1, score:-1} 인덱스를 생성합니다. 순서를 동일 시한 실행은 문제없이 실행됩니다. 반면 정렬 순서를 역으로 하지 않거나 순서를 다르게 한 경우는 정상 동작하지 않습니다.

> db.user.createIndex({userid:1, score:-1})

# 실행 시 문제 없이 진행 
> db.user.find({}).sort({ userid:1,score:-1})
> db.user.find({}).sort({ userid:-1,score:1})

# RAM exceeded error 발생
> db.user.find({}).sort({ userid:1,score:1})
> db.user.find({}).sort({ score:-1,userid:1})

- 특징 3. Prefixes

 Index prefixes란 조회 시 왼쪽 인덱스부터 적용되는 부분집합 인덱스를 말합니다. 정의가 이해하기 어려우니 아래의 예시로 이해해 봅시다. a, b, c, d 복합 인덱스를 생성할 때 { a: 1 }~{ a:1, b: 1, c: 1, d: 1 }까지 적용됩니다. 따라서 이런 인덱스를 생성할 시 {a:1} 인덱스가 정의되어 있다면, 삭제해도 상관없습니다. 왜냐면 { a:1, b: 1, c: 1, d: 1 } 인덱스로 인해 조회가 빠르게 이뤄질 것입니다.

- 생성된 인덱스: { a:1, b: 1, c: 1, d: 1 }

 아래 예시로 어떤 index prefixes 가 적용되는지 확인해 봅니다.

- 생성된 인덱스:  { "item": 1, "location": 1, "stock": 1 }

- 지원되는 쿼리: { item: 1 }
- 지원되는 쿼리: { item: 1, location: 1 }

- 지원하지 않는 조회 쿼리: "item" 필드 없이 "location" 필드만 존재 혹은 "stock" 필드만 존재 
- 지원하지 않는 조회 쿼리: "item" 필드 없이 "location", "stock" 필드만 존재 

 

- 특징 4. sort 연산은 non-prefix를 지원한다.

 sort 연산은 특징 3에서 배운 prefix 조건에 맞지 않아도 지원을 합니다. 그러나 이를 만족하기 위해서는 쿼리는 equality 조건은 prefix를 포함해야 합니다. 아래 예제로 이를 이해해 봅시다.

- 생성된 인덱스: { a:1, b: 1, c: 1, d: 1 }

 아래 표 예제는 위에 생성된 인덱스에 만족하는 쿼리입니다. 앞에 equality 조건은 모두 prefix를 만족합니다. 그러나 sort 부분은 prfix 조건을 만족하지 않지만 올바르게 사용된 쿼리 입니다.

https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/

 하지만 아래 쿼리는 위에 생성된 인덱스에 만족하지 못합니다. 첫 번째 쿼리는 equality 조건이 존재하지 않습니다. 두 번째 쿼리는 equality 조건이 prefix를 만족하지 못합니다.

> db.data.find( { a: { $gt: 2 } } ).sort( { c: 1 } )
> db.data.find( { c: 5 } ).sort( { c: 1 } )

 아래 예제로 실습을 진행해 봅시다. 이전에 생성한 인덱스는 drop 하고 진행합니다.

> db.user.createIndex({userid:1, score:1, age:1})

 

 아래 실습은 쿼리에 .explain("executionStats").executionStats.executionTimeMillis 를 넣어 실행 시간을 파악하였습니다. "userid" 없이 "score" 필드를 조건에 넣은 표 두 번째 쿼리는 실행 시간을 통해 적용이 안 된 것임을 알 수 있습니다. 또한, 6번째 쿼리도 prefix를 지키지 않아 적용이 안 됨을 알 수 있습니다.

쿼리 인덱스 생성 전 실행 시간(밀리 초)  인덱스 생성 후 실행 시간(밀리 초)  인덱스 적용 유무 
db.user.find({userid:20300}) 922 1 적용 o
db.user.find({score:53}) 1264 1109 적용 x
db.user.find({userid:{gt:3333}}) 965 0 적용 o
db.user.find({userid:11111}).sort({score:1}) 1090 0 적용 o
db.user.find({userid:1222,score:{$gt:22}}) 1010 0 적용 o
db.user.find({score:{$gt:22},age:22}) 1142 1082 적용 x
db.user.find({userid:2222, score:{$gt:22},age:22}) 1131 0 적용 o

 

- 특징 5. Index Intersection

 인덱스 교차란 별개의 인덱스가 교차해서 쿼리에 자동으로 적용되는 것입니다. 예를 들어 아래 두 인덱스가 개별 생성될 시 아래의 쿼리는 인덱스 교차로 인해 자동으로 인덱스가 적용됩니다.

- 인덱스 1: { qty: 1 }
- 인덱스 2: { item: 1 }

> db.orders.find( { item: "abc123", qty: { $gt: 15 } } )

 인덱스 교차로 동작했는지 확인하기 위해 explain() 명령어를 사용합니다. 해당 명령어 사용 시 AND_SORTED 나 AND_HASH 가 발견되면 인덱스 교차로 동작된 것입니다. 해당 특징에 대한 자세한 부분은 mongodb 문서에서 확인해 봅니다.

 

출처 : https://ryu-e.tistory.com/1

 

MongoDB index 개념과 indexing 전략

이번 시간에는 mongodb index에 대해 알아보려고 합니다. 어떤 조회 쿼리를 추가했는데 그 쿼리가 너무 느렸던 경험과 기존 프로젝트에 조회 쿼리가 데이터가 쌓일수록 느려져 문제가 되었던 적이

ryu-e.tistory.com

 

 인덱스 생성

인덱스를 생성 할 땐, 다음과 같은 createIndex() 메소드를 사용합니다. 파라미터는 인덱스를 적용할 필드를 전달합니다. 값을 1로하면 오름차순으로, -1로 하면 내림차순으로 정렬합니다.

db.COLLECTION.createIndex( { KEY: 1 } )

다양한 예제를 통하여 인덱스 생성을 배워보도록 하겠습니다.

예제1 단일 필드 인덱스 생성

db.report.createIndex( { score: 1 } )

score 필드에 인덱스를 걸어줍니다.

이 인덱스는 다음과 같은 쿼리를 할 때 효율적으로 실행하게 해줍니다.

db.report.find( { score: 57 } )
db.report.find( { score: { $gt: 60 } } )

예제2 복합 필드 인덱스 생성

db.report.createIndex( { age: 1, score: -1} )

이렇게 여러 필드를 넣어 인덱스를 생성하면 age를 오름차순으로 정렬한 상태에서 score 는 내림차순으로 정렬합니다.

 인덱스 속성

인덱스에 속성을 추가 할 땐 createIndex() 메소드의 두번째 인자에 속성값을 document 타입으로 전달해주면 됩니다.

db.COLLECTION.createIndex( { KEY: 1 }, {  PROPERTY: true } )

인덱스에 적용 할 수 있는 4가지 속성이 있는데요, 한번 이에 대해 알아보고, 예제를 통해 사용법을 배워보도록 하겠습니다.

Unique (유일함) 속성

_id 필드처럼 컬렉션에 단 한개의 값만 존재 할 수 있는 속성입니다.

예제3 email 인덱스에 unique 속성 적용

db.userinfo.createIndex( { email: 1 }, { unique: true } )

unique 속성은 다음처럼 복합 인덱스에도 적용 할 수 있습니다.

예제4 firstName 과 lastName 복합인덱스에 unique 속성 적용

db.userinfo.createIndex( { firstName: 1, lastName: 1 }, { unique: true } )

Partial (부분적) 속성

partial 속성은 document의 조건을 정하여 일부 document에만 인덱스를 적용 할 때 사용됩니다.

partial 속성을 사용하면, 필요한 부분에만 인덱싱을 사용하여 저장공간도 아끼고 속도를 더 높일수 있습니다.

예제5 visitors 값이 1000 보다 높은 document에만 name 필드에 인덱스 적용

db.store.createIndex( 
   { name: 1 }, 
   { partialFilterExpression: { visitors: { $gt: 1000 } } }
)

예제6 TLL 속성

이 인덱스 속성은 Date 타입, 혹은 Date 배열 타입의 필드에 적용 할 수 있는 속성입니다. 이 속성을 사용하여 document를 expire(만료) 시킬 수 있습니다. 즉, 추가하고 특정 시간이 지나면, document 를 컬렉션에서 제거합니다.

예제: notifiedDate 가 현재 시각과 1시간 이상 차이나면 제거

db.notifications.createIndex( { "notifiedDate": 1 }, { expireAfterSeconds: 3600 } )

 

document가 만료되어 제거 될 때, 시간이 아주 정확하지는 않습니다. 만료되는 document를 제거하는 thread는 매 60초마다 실행됩니다. 이점 유의해주세요.
출처: https://velopert.com/560

 

 

[MongoDB] 강좌 6편 Index 설정 | VELOPERT.LOG

이번 강좌는 MongoDB의 Index에 관한 내용입니다. Index란? Index는 MongoDB에서 데이터 쿼리를 더욱 효율적으로 할 수 있게 해줍니다. 인덱스가 없이는, MongoDB는 collection scan – 컬렉션의 데이터를 하나하

velopert.com

 

 

 

반응형

'DataBase > MongoDB' 카테고리의 다른 글

기본 개념  (0) 2023.02.07
반응형

mongoDB의 객체는 관계형 데이터베이스와 많은 공통점을 가지고 있으며 일부 명칭은 다르나 비슷한 역할을 수행합니다. 다음은 mongoDB의 객체와 관계형 데이터베이스의 객체를 비교한 내용입니다.

mongoDB관계형 DB

데이터베이스
(Database)
데이터베이스
(Database)
컬렉션
(Collection)
테이블
(Table)
도큐먼트
(Document)
로우
(Row)
필드
(Field)
칼럼
(Column)
인덱스
(Index)
인덱스
(Index)

데이터 조작어

mongoDB의 데이터 조작어(DML - Data Manipulation Language)는 SQL 문법을 사용하지 않고 자바스크립트 기반의 명령어와 JSON 도큐먼트를 인자로 사용하지만, 관계형 데이터베이스의 데이터 조작어와 형태만 다를 뿐 비슷한 역할을 수행합니다. 다음은 mongoDB와 관계형 데이터베이스의 대표적인 데이터 조작어를 비교한 내용입니다.

항목mongoDB관계형 DB

입력 db.member.insert( { no : "C001", age : 45, status : "A" } ) insert into member(no, age, status) values('C001', 45, 'A')
수정 db.member.update( { age : { $gt : 25 } }, { $set : { status : "C" } }, { multi : true } ) update member set status = 'C' where age > 25
삭제 db.member.remove( { no : "C001" } ) delete from member where no = 'C001'
조회 db.member.find( { no : "C001" } ) select * from member where no = 'C001'
반응형

'DataBase > MongoDB' 카테고리의 다른 글

MongoDB index  (0) 2023.02.10

+ Recent posts