본문 바로가기

mongoDB

[DB] MongoDB Index 개념과 설계 전략

반응형

인덱스, Index 란?

책의 마지막 쪽에 있는 '인덱스', '찾아보기' 와 비슷하다. 책의 '인덱스'에 적힌 페이지 번호는 해당 데이터의 주소에 비유할 수 있다. DBMS도 사람이 책의 인덱스를 보고 해당 페이지를 찾는 것처럼 데이터를 찾는다. 데이터와 저장된 위치를 키와 값의 쌍 (key-value pair)으로 관리한다.  

 

DB의 검색을 신속하게 하기 위해 데이터의 순서를 미리 정해두는 과정이다. 특정 데이터 필드를 인덱스로 지정하여 검색 결과를 빠르게 얻을 수 있다. 

 

DBMS에서 인덱스는 데이터의 저장성능을 희생해서 상대적으로 데이터의 읽기 속도를 향상시키는 존재 -> 테이블에 인덱스 하나를 더 추가할지 말지는 데이터의 저장 속도를 얼마나 더 희생할 수 있는지, 읽기(조회) 속도를 얼마나 더 빠르게 만들어야 하는지 조율하면서 결정해야한다. 

 

많은 도큐먼트 (전체 컬렉션 도큐먼트의 15~20% 이상)를 읽어야 할 때에는 인덱스를 이용하지 않고 컬렉션 스캔 (풀 테이블 스캔) 으로 필요한 레코드를 가려내는 방식이 더 좋다고 한다.

 

하나의 쿼리에 하나의  Index가 유효하다. 두 개의 Index가 필요하다면 복합 index를 사용한다. 

 

 

 

INDEXES

MongoDB는 쿼리를 수행할 때 스스로 어떻게 처리할지 고민하고 최선의 방법으로 인덱스를 활용한다. 적합하지않은 인덱스가 지정되었을 때 비효율적이라고 판단되면 사용하지 않기도 한다. 좋은 인덱스 전략을 세우는 가장 중요한 요소는 반복적인 테스트이다. 인덱스 검사를 위해 주로 사용하는 매서드는 hint()와 explain()이 있다. 

 

 

A Single Field Index, 단일 인덱스

쿼리에서 단 하나의 Key만을 이용하면 단일 키 인덱스를 사용해야 한다. 

db.[collectionName].createIndex({ isDone: 1 })     
// 1은 오름차순, -1은 내림차순을 의미 

1 은 오름차순 -1은 내림차순을 의미한다. 일렬로 나열되어 있기 때문에 오름차순이든 내림차순이든 동일한 성능을 낸다. 하나의 쿼리에서 단일 인덱스 두 개를 사용하면 MongoDB가 그 중 제일 효율적인 인덱스를 선택하지만 그 결과가 항상 최선은 아닐 수도 있다. 

db.[collectionName].find().sort({ isDone: 1 }) // 오름차순으로 찾는다
db.[collectionName].find().sort({ isDone: -1 }) // 내림차순으로 찾는다 - 같은 일렬로 나열된 데이터라 성능은 동일

위의 두 가지 find().sort() 쿼리의 성능은 동일하다 ! 

 

 

 

 

Compound Index (Multiple Fields Index) , 복합 인덱스

검색어에 여러 키가 사용된다면 복합 인덱스로 정의해주어야 한다.

db.[collectionName].createIndex({ userid: 1, score: -1 })

userid와 score 두 개의 복합 인덱스를 설정했다고 해서 각각 다른 쿼리에 각각의 키로 검색 할 수는 없다. userid와 score두 인덱스가 함께 저장되어 있고 userid는 오름차순으로 정렬되어 있지만 score는 그렇지 않다. 하지만 동일한 userid 가 여러개의 score를 가지고 있다면 해당 userid의 내의 score정렬은 내림차순으로 정해진다. 

위와 같이 복합 인덱스를 설정했다면 쿼리문을 작성할 때도 순서를 맞춰주어야 효율적인 검색이 가능하다. ( 또는 정 반대의 경우로) 

db.[collectionName].createIndex({ userid: 1, score: -1})

db.[collectionName].find().sort({ userid: 1, score: -1 })   // 성능이 좋다
db.[collectionName].find().sore({ userid: -1, score: 1 })   // 성능이 좋다 

db.[collectionName].find().sore({ score: -1, userid: 1 })   // 성능이 안좋다
db.[collectionName].find().sore({ userid: -1, score: 1 })   // 성능이 안좋다

 단일 인덱스의 경우 일렬로 나열된 데이터 구조 덕에 내림차순이든 오름차순이든 성능에 차이가 없었다. 마찬가지로 컴파운드 인덱스를 구성하는 키들의 방향이 서로 다르더라도 데이터 구조는 일렬로 나열되어 있기 때문에 각 키의 방향 조합만 맞춰주면 동일한 효과를 가져온다. 



 

 

 

 

Index Prefix, 인덱스 프리픽스

정의된 복합 인덱스의 앞 쪽부터 포함되는 부분집합의 인덱스를 Prefix라고 말한다. (꼭 앞에서부터 순차적이어야 한다.) 즉, 복합 인덱스를 먼저 선언 후에 프리픽스를 사용할 수 있다.  아래 예시를 보면

db.[collectionName].createIndex( {a:1, b:1, c:1, d:1 } )    // 복합 인덱스 설정

// 위의 복합인덱스에서 사용할 수 있는 프리픽스들 
{ a:1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }
{ a: 1, b: 1, c: 1, d: 1 }
db.collectionName.find().sort({a : 1})                                   // index prefix { a: 1 }
db.collectionName.find().sort({a : -1})                                  // index prefix { a: 1 }
db.collectionName.find().sort({a : 1, b : 1})                                  // index prefix { a: 1, b: 1 }
db.collectionName.find().sort({a : -1, b : -1})                               // index prefix { a: 1, b: 1 }
db.collectionName.find().sort({a : 1, b : 1, c : 1})                              // index prefix { a: 1, b: 1, c: 1 }
db.collectionName.find({a: { $gt: 4 } }).sort( { a: 1, b: 1 } ).             // index prefix { a: 1, b: 1 }

예를 들어, "a" field없이 "b" field 조회하는 (순차적으로 있지않은) 쿼리들

 

 

 

 

 

Index Intersection

인덱스 교차란 인덱스가 교차해서 쿼리에 자동 적용되는 것을 말한다. 예를 들면, 

db.collectionName.createIndex({ qty: 1 })
db.collectionName.createIndex({ item: 1 })

-> db.collectionName.find( { item: 'abc', qty: { $gt: 15 } } )       // 인덱스가 적용된다. 

위의 쿼리에 .explain()을 사용해보면 AND_SORTED or AND_HASH가 나온다. 

 

 

 

 

DB 처리 성능을 최적화하기 위해 index의 이해는 매우 중요하다고 한다! 가장 좋은 쿼리를 만들기 위한 고민과 노력을 계속 하기! 

 

 

 

 

 

 

 

 

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

 

Use Indexes to Sort Query Results — MongoDB Manual

Docs Home → MongoDB ManualSince indexes contain ordered records, MongoDB can obtain the results of a sort from an index with which includes the sort fields. MongoDB may use multiple indexes to support a sort operation if the sort uses the same indexes as

docs.mongodb.com

 

반응형