MongoDB

[MongoDB] Ch6 - 특수 인덱스와 컬렉션 유형

잭피 2021. 12. 24. 09:43

6장에서는 아래와 같은 내용을 알아보자

  • 큐 같은 데이터를 위한 제한 컬렉션
  • 캐시를 위한 TTL 인덱스
  • 단순 문자열 검색을 위한 전문 인덱스
  • 2D 구현 및 구면 기하학을 위한 공간 정보 인덱스
  • 대용량 파일 저장을 위한 GridFS

6.1. 공간 정보 인덱스

몽고DB는 2dsphere와 2d라는 공간 정보 인덱스를 가진다

WGS84 좌표계를 기반으로 지표면을 모델링하는 구면 기하학으로 작동한다

1. 공간 정보 쿼리 유형

공간 정보 쿼리는 교차, 포함, 근접이라는 세 가지 유형이 있다

{”$geometry” : geoJsonDesc}와 같은 GeoJSON 객체로 지정한

$geoIntersects 연산자를 사용해 쿼리 위치와 교차하는 도큐먼트를 찾을 수 있다

2. 공간 정보 인덱스 사용

몽고DB의 공간 정보 인덱스를 사용하면 특정 지역과 관련된 모양과 점이 포함된 컬렉션에서 공간 쿼리를 효율적으로 실행할 수 있다

쿼리에서의 2D vs. 구면 기하학

공간 정보 쿼리는 쿼리와 사용 중인 인덱스 유형에 따라 구면 또는 2D(평면) 구조를 사용한다

2d 인덱스는 구에서 평면 기하학과 거리 계산을 모두 지원한다는 점에 유의하자

왜곡

구면 기하는 지도에 시각화하면 왜곡이 있는데, 지구와 같은 3차원 구를 평면에 투사하는 특성때문이다

3. 복합 공간 정보 인덱스

공간 정보 인덱스는 다른 인덱스 종류와 마찬가지로 다른 필드와 묶음으로써 더 복잡한 쿼리를 최적화할 수 있다

4. 2d 인덱스

비구체지도(비디오 게임 지도, 시계열 데이터 등)에는 2dsphere 대신 2d 인덱스를 사용한다

6.2 전문 검색을 위한 인덱스

몽고DB의 text 인덱스는 전문 검색의 요구 사항을 지원한다

애플리케이션 사용자가 제목, 설명 등 컬렉션 내에 있는 필드의 텍스트와 일치시키는 키워드 쿼리를 하게 하려면 text 인덱스를 사용하자

정규 표현식을 이용해 쿼리하는 방식은 한계가 있다

쿼리 속도가 느리며, 문법과 같은 언어 특성을 반영하기도 쉽지 않다 (예를 들어, entry와 entries)

text 인덱스는 토큰화, stopword, 형태속 분석 등 일반적인 요구 사항을 지원한다

text 인덱스는 비용이 많이 발생한다

1. 텍스트 인덱스 생성

# title, body 필드 내 용어를 기반으로 인덱스를 생성
db.articles.createIndex({"title": "text", "body" : "text"})

# title과 body필드에 가중치를 주기
db.articles.createIndex({"title": "text", "body" : "text"}, { "weight" : {
 "title":3, "body":2 })

# % **에 인덱스를 만들면 도큐먼트 모든 문자열 필드에 전문 인덱스를 생성할 수 있다
db.articles.createIndex({"$**" : "text"})

2. 텍스트 검색

“$text” 쿼리 연산자를 사용해 text 인덱스가 있는 컬렉션에 텍스트 검색을 수행하자

db.articles.find({"$text" : {"$search" : "impact crater lunar"}}, {title : 1}).limit(10)

3. 전문 검색 최적화

전문 검색을 최적화하는 방법 2가지

  1. 다른 기준으로 검색 결과를 좁힐 수 있다면 복합 인덱스를 생성할 때 다른 기준을 첫 번째로 두고 전문 필드를 그 다음으로 둔다 (파티셔닝)
  2. 다른 기준을 뒤쪽에 두어 사용할 수도 있다

4. 다른 언어로 검색하기

default_language 옵션으로 언어를 지정할 수 있다

default는 english 이다

6.3 제한 컬렉션

몽고DB의 ‘일반적인’ 컬렉션은 동적으로 생성되고 추가적인 데이터에 맞춰 크기가 자동으로 늘어난다

몽고DB는 제한 컬렉션이라는 다른 형태의 컬렉션을 지원한다 (미리 생성돼 크기가 고정)

제한 컬렉션은 환형 큐처럼 동작한다

빈 공간이 없으면 가장 오래된 도큐먼트가 없어지고 새로운 도큐먼트가 그 자리를 차지한다

일반적으로 몽고DB TTL 인덱스는 와이어드타이거 스토리지 엔진에서 더 나은 성능을 발휘하므로 제한 컬렉션보다 권장된다

TTL 인덱스는 날짜 유형 필드 값과 인덱스 TTL 값을 기반으로 일반 컬렉션에서 데이터가 만료되고 제거된다

 

💡 제한 컬렉션은 샤딩될 수 없다. (제한 컬렉션에서 도큐먼트 크기가 갱신이나 대체로 인해 변경되면 작업이 실패한다)

 

제한 컬렉션은 유연성은 부족하지만 로깅에는 나름 유용하다

1. 제한 컬렉션 생성

제한 컬렉션은 일반 컬렉션과 달리 명시적으로 생성돼야 한다

db.createCollection("my_collection",{"capped":true, "size":100000});

# 도큐먼트 수를 제한할 수도 있다
db.createCollection("my_collection",{"capped":true, "size":100000, "max" : 100});

제한 컬렉션은 일단 생성되면 변경할 수 없다 (속성을 변경하려면 삭제 후 재생성해야 한다)

 

💡 따라서 크기가 큰 컬렉션을 생성하기 전에 신중히 검토하자

 

기존 일반 컬렉션을 제한 컬렉션으로 변환할 수도 있다

db.runCommand({"convertToCapped" : "test", "size" : 10000});

제한 컬렉션을 일반 컬렉션으로 변환하는 방법은 없다

2. 꼬리를 무는 커서

꼬리를 무는 커서는 결과를 모두 꺼낸 후에도 종료되지 않는 특수한 형태의 커서이다

(tail -f 명령어에서 영감을 받아 만들어졌다)

tail -f와 비슷하게 결과를 지속적으로 꺼내는 기능을 수행한다

일반 컬렉션에서는 입력 순서가 추적되지 않기 때문에 꼬리를 무는 커서는 제한 컬렉션에서만 사용한다

6.4 TTL 인덱스

TTL 인덱스를 이용해서 각 도큐먼트에 유효 시간을 설정할 수 있다

도큐먼트는 미리 설정한 시간에 도달하면 지워진다

이런 인덱스는 세션 스토리지와 같은 문제를 캐싱하는데 유용하다

expireAfterSeconds 옵션을 명시해 시간을 지정한다

# 24시간 뒤 타임아웃
db.sessions.createIndex({"lastUpdated":1, {"expireAfterSeconds" : 60*60*24}

6.5 GridFS로 파일 저장하기

GridFS는 몽고DB에 대용량 이진 파일을 저장하는 메커니즘이다

파일을 저장할 때 GridFS를 고려하는 데 몇 가지 이유가 있다

  • GridFS를 이용하면 아키텍처 스택을 단순화할 수 있다
  • 몽고DB를 위해 설정한 기존의 복제나 자동 샤딩을 이용할 수 있어, 파일 스토리지를 위한 장애 조치와 분산 확장이 더욱 쉽다
  • 사용자가 올린 파일을 저장할 때 특정 파일 시스템이 갖는 문제를 피할 수 있다
  • 예를 들어 GridFS는 같은 디렉터리에 대량의 파일을 저장해도 문제가 없다

몇 가지 단점도 있다

  • 성능이 느리다
  • 도큐먼트를 수정하려면 도큐먼트 전체를 삭제하고 다시 저장하는 방법밖에 없다
  • 몽고DB는 파일을 여러 개의 도큐먼트로 저장하므로 한 파일의 모든 청크에 동시에 락을 걸 수 없다

 

💡 GridFS는 큰 변화가 없고 순차적인 방식으로 접근하려는 대용량 파일을 저장할 때 일반적으로 최선의 메커니즘이다

1. GridFS 시작하기 : mongofiles

mongofiles는 GridFS에서 파일을 올리고, 받고, 목록을 출력하고, 검색하고, 삭제할 때 등에 사용한다

2. 몽고DB 드라이버로 GridFS 작업하기

모든 클라이언트 라이버리는 GridFS API를 가진다

ex) PyMongo

3. 내부 살펴보기

GridFS는 파일 저장을 위한 간단한 명세이며 일반 몽고DB 도큐먼트를 기반으로 만들어졌다

GridFS 기본 개념은 대용량 파일을 청크로 나눈 후 청크를 도큐먼트로 저장할 수 있다는 것이다

청크 컬랙션 내 각 도큐먼트 구조

{
	"_id" : ObjectId("..."),
  "n" : 0,
  "data" : BinData("..."),
  "files_id" : ObjectId("...")
}
  • files_id : 청크에 대한 메타데이터를 포함하는 파일 도큐먼트의 _id
  • n : 다른 청크를 기준으로 하는 파일 내 청크의 위치
  • data : 파일 내 청크의 크기(바이트 단위)

각 파일의 메타데이터는 기본적으로 별도의 컬렉션인 fs.files에 저장된다

files 컬렉션 내 각 도큐먼트는 GridFS에서 하나의 파일을 나타내며, 해당 파일과 관련된 어떤 메타데이터든 포함할 수 있다.

사용자 정의 키 외에도 GridFS 명세에서 강제하는 키가 몇 개 더 있다

  • _id : 파일의 고유ID, 각 청크에서 file_id 키의 값으로 저장
  • length: 파일 내용의 총 바이트 수
  • chunkSize : 파일을 구성하는 각 청크의 크기 (바이트)
  • uploadDate : GridFS에 파일이 저장된 시간
  • md5 : 서버에서 생성된 파일 내용의 MD5 체크썸