[몽고 디비 문서 번역] Indexes

KIMPEUPEU·2019년 2월 18일
3

부족한 영어 실력으로 개인 공부를 하기 위해 작성한 글입니다.
단순히 참고 사항으로 사용하시고 오역 및 오타는 알려주시면 감사합니다.

출처: https://docs.mongodb.com/manual/indexes/

인덱스

인덱스는 몽고비디에서 쿼리의 효율적인 실행을 지원한다. 인덱싱이 없이는 몽고디비는 콜렉션 스캔을 실행해야한다. 예를들어 쿼리문에 일치하는 도큐먼트를 선별하기 위해 컬렉션 내의 모든 도큐먼트를 스캔해야한다. 만약 적절한 인덱스가 쿼리에 대해 존재하면, 몽고디비는 검사해야하는 도큐먼트의 수를 줄이는데 인덱스를 사용한다.

인덱스는 콜렉션의 데이터셋의 작은 일부를 저장하고 있는 특별한 데이터 구조이다. (in an easy to traverse form 모르겠음.) 이 인덱스는 특정한 필드나 필드 묶음의 값을 저장하고 이는 필드들은 필드의 값으로 정렬되어 있다. 이 인덱스의 해당 정렬은 효율적인 동등 검색(equality matches)와 거대한 쿼리 연산을 지원한다. 게다가, 몽고디비는 이 인덱스에 있는 정렬을 이용해 정렬된 결과를 반환할 수도 있다.

다음에 보이는 다이어그램은 인덱스를 이요해 도큐먼트를 검색하고 정렬하는 쿼리를 묘사하고 있다.

기초적으로, 몽고디비에 있는 인덱스들은 다른 데이터베이스 시스템들에 있는 인덱스와 유사하다. 몽고디비는 인덱스를 콜렉션 수준에서 정의하고 몽고디비 콜렉션의 도큐먼트 중 어떤 필드나 서브필드에 인덱스를 적용할 수 있다.

기본 _id 인덱스

몽고디비는 콜렉션의 생성 중 _id 필드에 유닉크 인덱스를 생성한다.(혼동을 방지하기 위해 unique index는 바로 쓰겠음.) 이 _id 인덱스는 클라이언트가 같은 _id 값이 있는 두 개의 도큐먼트를 삽입하는 것을 방지한다. 당신은 _id 필드는 뺄 수 없다.(누락시킬 수 없다?)

NOTE:
샤디드 클러스터에서, _id필드를 샤드 키로 사용하지 않으면 당신의 어플리케이션에서 에러를 예방하기 위해 _id 필드에서 값의 고유함을 반드시 보장해줘야한다. 이는 대부분 일반적인 자동 생성된 ObjectId를 사용해 처리된다.

몽고디비 쉘에서 인덱스를 생성하기 위해, db.collection.createIndex()를 사용해라.

db.collection.createIndex( <key and index type specification>, <options> )

다음 예시는 내림차순하는 단일 인덱스를 네임필드에 생성한 것이다.

db.collection.createIndex( { name: -1 } )

db.collection.createIndex메소드는 같은 명시의 인덱스가 생성된지 않았을때만 인덱스를 생성한다.

몽고디비 인덱스는 B-tree 데이터 구조를 사용한다.

인덱스 종류

몽고디비는 특정한 타입의 데이터와 쿼리를 지원하기 위해 다양한 인덱스 타입을 제공하고 있다.

싱글 필드(Single Field)

몽고디비가 정의한 _id 인덱스에 이어, 몽고디비는 하나의 도큐먼트에 단일 필드에 대해 사용자 정의 오름차순/내림차순 인덱스의 생성을 제공한다.

싱글 필드 인덱스와 정렬 연산에 대해, 인덱스 키의 정렬 순서(오름/내림차순)는 인덱스의 다른 방향으로 다각측량을 할 수 있어 문제되지 않습니다.
(traverse 할 수 있다고하는데, 해당 단어의 늬앙스를 잘 몰라 흐름상 여러 방향으로 측정하는 의미로 사용되는듯함 댓글 요망)

컴파운드 인덱스(Compound Index)

몽고디비는 또한 여러 필드에 대해 사용자 정의 인덱스를 지원합니다.
컴파운드 인덱스에서 나열되는 필드의 순서는 매우 중대합니다. 에를 들어, 한 컴파운드 인덱스가 { userid: 1, score: -1 }이라고 구성되어 있다면, 그 인덱스는 먼저 userid로 정렬되고 각각의 userid내에서 score로 정렬됩니다.

컴파운드 인덱스와 정렬 연산에 대해서, 인덱스 키의 정렬 순서는 인덱스가 정렬 연산을 지원하는지를 결정할 수 있습니다.

멀티키 인덱스(Multikey Index)

몽고디비는 배열에 저장된 내용을 인덱스하기 위해 멀티키 인덱스를 사용합니다. 만약 배열 값을 가지는 필드를 인덱스하려고 하면, 몽고디비는 배열의 모든 요소에 대해 개별의 인덱스 개체들를 생성합니다. 이 멀티키 인덱스는 그 배열들의 요소나 요소들에 매치하여 배열을 가지는 도큐먼트를 선택하는 쿼리를 가능하게 합니다. 몽고디비는 인덱스된 피드가 배열 값을 가지면 자동적으로 멀티키 인덱스를 생성할지를 결정합니다. 당신이 명시적으로 멀티키 타입을 지정할 필요는 없습니다.

지오스파셜 인덱스(Geospatial Index)

지리 좌표 데이터의 효율적인 쿼리를 제공하기 위해, 몽고디비는 두 개의 특별한 인덱스를 제공합니다.

  • 2d indexes: 평면 기하학을 이용해 결과를 제공합니다.
  • 2dsphere indexes: 구체 기하학을 이용해 결과를 제공합니다.

텍스트 인덱스(Text Index)

몽고디비는 콜렉션의 문자 내용을 검색을 지원하는 텍스트 인덱스 타입을 제공합니다. 이 문자인덱스는 정지단어(예, 'the', 'a', 'or')를 저장하지 않고 오직 어원을 저장하기 위해 콜렉션의 단어들을 stem한다.
(뭔말인지 1도 모르겠음...)

해쉬 인덱스(Hashed Index)

해쉬 기반의 샤딩을 제공하기 위해, 몽고디비는 필드의 값의 해쉬를 인덱스하는 해쉬 인덱스 타입을 제공한다. 이러한 인덱스는 이들 범위 내 값에 더욱 무작위적인 분포를 가지고 있다. 하지만 단순히 동등 매치만 지원하고 범위 기반 쿼리를 지원하지 않는다.

인덱스 특성

유니크 인덱스(Unique Index)

인덱스에 대한 유니크 특성은 몽고디비가 인덱스된 필드에 대해 중복된 값을 가질 수 없게 한다. 유니크 제약과 다르게 유니크 인덱스는 기능상 다른 몽고디비 인덱스와 교체 가능하다.

파셜 인덱스 (팔셜...?, Partial Indexes)

3.2 버전에 새로 들어옴

파셜 인덱스는 오직 특정한 필터 표현을 경험한 콜렉션에 있는 도큐먼트에 인덱스된다. 콜렉션에 도큐먼트의 부분 집합을 인덱싱 함으로, 파셜 인덱스는 인덱스의 생성과 유지에 대해 적은 용량을 요구하고 성능 비용을 감소시킨다.

파셜 인덱스는 스팔스 인덱스(sparse indexes)의 기능성의 확대집합(기능성을 포괄하는?)을 제공하고 스팔스 인덱스보다 선호되어야한다.

스팔스 인덱스 (Sparse Indexes)

인덱스의 스팔스 특성은 오직 인덱스된 필드를 가지는 도큐먼트에 대한 개체를 포함하는 인덱스임을 보장한다. 이 인덱스는 인덱스된 필드가 없는 도큐먼트는 무시한다.

당신은 스팔스 인덱스 옵션을 유니크 인덱스 옵션과 조합하여 필드에 대해 중복된 값을 가지는 도큐먼트를 걸러낼 수 있다. 하지만 인덱스 키를 가지지 않는 도큐먼트는 무시한다.

TTL 인덱스 (TTL Indexes)

TTL 인덱스는 일정 시간을 지난 후 콜렉션에서 자동적으로 도큐먼트를 제거할 수 있는데 사용할 수 있는 특별한 인덱스이다. 한정된 시간동안 데이터베이스에서 유지되어야하는 이벤트 데이터, 로그, 세션 정보 같은 정보의 특정 타입에 대해 이상적이다.

인덱스 사용

인덱스는 읽기 연산의 효율을 상승 시킬 수 있다. Analyze Query Performance tutorial 에서 인덱스가 있고 없고한 쿼리들의 실행 통계의 예를 제공한다.

인덱스와 콜레이션(Indexes and Collation)

버전 3.4에 새로 생김

콜레이션은 사용자가 소문자와 강조 표시에 대한 방식에 처럼 문자열 비교에 대한 언어적 특정 방식을 명시할 수 있도록 한다.

문자열 비교에 대한 인덱스를 사용하기 위해, 연산은 반드시 같은 콜레이션을 명시해야한다. 이는 콜레이션을 가진 인덱스가 연산이 다른 콜레이션을 명시하고 있으면 인덱스된 필드에 문자열 비교를 수행하는 연산을 할 수 없기 때문이다.

예를들어, myColl이 문자열 필드 categoryfr 콜레이션으로 인덱스를 가지고 있다

db.myColl.createIndex( { category: 1 }, { collation: { locale: "fr" } } )

인덱스로 같은 콜레이션을 명시하고 있는 다음 쿼리 연산은 인덱스를 사용한다.

db.myColl.find( { category: "cafe" } ).collation( { locale: "fr" } )

그러나 기본적으로 적용되는 '단순' 이진 콜레이터를 사용하는 다음 쿼리 연산은 인덱스를 사용하지 못 한다.

db.myColl.find( { category: "cafe" } )

컴파운드 인덱스에 인덱스 접두사 키가 문자열, 배열 그리고 내장 도큐먼트가 아닌 것에 대해, 다른 콜레이션을 명시한 연산이 인덱스 접두사 키에 비교를 지원하는 인덱스를 여전히 사용할 수 있다.

예를 들어, myColl 콜렉션이 숫자형 필드인 scoreprice 그리고 문자열 필드 category에 컴파운드 인덱스를 가지고 있으면 이 인덱스는 문자열 비교에 대해 fr 콜레이션 로케일을 가지고 생성된다.
(먼소린지...)

db.myColl.createIndex(
   { score: 1, price: 1, category: 1 },
   { collation: { locale: "fr" } } )

문자열 비교에 대해 '단순' 이진 콜레이션을 사용하는 다음 연산은 인덱스를 사용할 수 있다.

db.myColl.find( { score: 5 } ).sort( { price: 1 } )
db.myColl.find( { score: 5, price: { $gt: NumberDecimal( "10" ) } } ).sort( { price: 1 } )

인덱스된 category필드에 문자열 연산에 대해 '단순' 이진 콜레이션을 사용하는 다음 연산은 쿼리의 오직 score: 5 부분을 이행하는데 인덱스를 사용할 수 있다.

다음 인덱스들은 단순 이진 비교만 지원하고 콜레이션을 지원하지 않는다.

  • text indexes
  • 2d indexes
  • geoHaystack indexes

덮힌 쿼리(?)(Covered Queries)

그냥 커버드 쿼리라 하자
쿼리 조건과 쿼리의 프로젝션이 단지 인덱스된 필드만 포함할때, 몽고디비는 어떤 도큐먼트에서 스캔하거나 메모리로 도큐먼트를 가져오거나 하지 않고 직접적으로 인덱스에서 결과를 낸다. 이러한 커버드 쿼리는 매우 효율적일 수 있다.

인덱스 인터섹션(Index Intersection)

버전 2.6에 추가됨
몽고디비는 쿼리를 채우기 위해 인덱스의 인터섹션을 사용할 수 있다. 복잡적인 쿼리 조건을 명시하고 있는 쿼리에 대해 만약 한 인덱스가 쿼리 조건의 부분을 채울 수 있고 다른 인덱스가 쿼리 조건의 나머지 부분을 채울 수 있으면, 몽고디비는 쿼리를 채우는 두 인덱스의 인터섹션을 사용할 수 있다. 컴파운드 인덱스를 사용하거나 인덱스 인터세션을 사용하는 건 특정한 쿼리와 시스템에 대해 더욱 효율적이다.

제약

특정 제약은 인덱스 키의 길이나 콜렉션당 인덱스 수 같은 특정 제약이 인덱스에 적용 될 수 있다.

추가적인 고려사항

비록 인덱스가 쿼리 성능을 향상 시킬 수 있지만 인덱스 또한 몇가지 운용상 고려사항이 있다. 인덱스에 대해 운용상 고려해야하는 것들을 보라

만약 당신의 콜렉션이 방대한 양의 데이터를 가지고 있고 당신의 어플리케이션이 인덱스를 구성하는 동안 데이터에 접근해야하한다면 인덱스를 백그라운드에서 구성하는 것을 고려하라.(백그라운드 구축하기)

레플리카 셋에 대해 인덱스를 구성하거나 재구성하려면 레플리카 셋에 인덱스 구성하기를 봐라

출처: https://docs.mongodb.com/manual/indexes/

profile
안녕하세요 김프프입니다.

1개의 댓글