https://wikibook.co.kr/real-mongodb/
Real MongoDB: 대용량 데이터 처리를 위한
MongoDB의 "Know-How"가 아닌 "Know-Why"를 전달해 드립니다! MongoDB 메뉴얼은 아주 간결하고 기본적인 내용에 충실하게 작성되어 있다. 하지만 문법이나 명령만으로는 DBMS를 사용할 수 없다. 내부 작동 ��
wikibook.co.kr
책을 읽고 일부 내용을 정리하였습니다.
01. MongoDB
1.1 데이터베이스 트렌드
- 5~6년전까지만 해도 관계형 테이터베이스 중심
- 2012년경부터 HBase와 카산드라를 포함한 여러 NoSQL DBMS 들이 오픈 소스 기반으로 급성장
- 2012년 구글 Spanner라는 분산 트랜젹션을 지원하는 데이터베이스 논문 발표
- Spanner가 가진 가장 큰 특징
- 관계형 데이터베이스
- 트랜잭션 지원
- 분산 처리
- 재해 복구(Disaster Recovery)
- Sharding & Re-Balancing
- 데이터 복제 & 자동 복구
- 처음 하나를 제외하면 MongoDB가 제공하는 기능과 모두 일치
- 두 번째 특징은 GPS 수신기를 장착한 서버를 사용하기 때문에 MongoDB 와 같은 오픈소스에서 아직 구현되지 쉽지 않음
- 나머지 4가지 특징은 MySQL 서버가 지원하지 못하는 한계점
- Spanner가 가진 가장 큰 특징
1.2 MongDB의 라이선스
- 오픈 소스 데이터베이스
1.3 MongoDB 버전
- 첫번째 숫자 : 메이저 버전
- 두번재 숫자 : 마이너 버전
- 마지막 숫자
- 홀수 번호는 개발 버전
- 짝수 번호는 안정(릴리즈) 버전
- 항상 개발 버전은 안정 배포판 버전보다 큰 마이너 버전 번호가 할당
1.4 MongoDB vs. RDBMS(MySQL)
- 스키마 프리(Schema-Free)
1.5 MongoDB vs. NoSQL(HBase)
- HBase : 각 컬럼을 별도의 파일로 저장하는 것이 아니라, 하나의 테이블 안에서도 관련된 컬럼을 묶어서 여러 개의 컬럼 패밀리를 만들고, 이 컬럼 패밀리 단위로 데이터 파일을 생성하여 관리
- MongoDB : 한 테이블 데이터(Document)는 하나의 데이터 파일로 저장
1.6 MongoDB 아키텍처
- 각 프로그래밍 언어별로 적절한 클라이언트 드라이버를 이용해서 MongoDB 서버와 통신
1.7 MongoDB 배포 형태
- 1.7.1 단일 노드(Standalone) : 기존의 RDBMS가 작동하는 방식
- 1.7.2 단일 레플리카 셋(Single Replica-set) : 하나의 프라이머리 노드와 1개 이상의 세컨드리 노드로 구성
- 1.7.3 샤딩된 클러스터(Sharded Cluster)
- 샤딩된 클러스터에 참여하고 있는 각각의 레플리카 셋을 샤드라고 함.
- 샤드에 어떤 데이터를 가지는지에 대한 정보는 MongoDB 컨피그(Config) 서버가 관리
07. 데이터모델링
7.1 데이터베이스와 컬렉션
- 7.1.1 네임스페이스 : 데이터베이스 이름과 컬렉션의 이름 조합
- ex) blog.articles : blog 데이터베이스의 articles 컬렉션을 지칭하는 네임스페이스
- 7.1.2 데이터베이스: 주로 서비나 데이터의 그룹을 만들기 위해서 사용하는 물리적인 개념
- MongoDB 3.0부터 데이터베이스 수준의 잠금을 조금 더 세분화해서 컬렉션 수준의 잠금으로 개선
- 7.1.3 컬렉션 : RDBMS에서 주로 테이블이라고 부르는 객체
- MongDB의 컬렉션은 가능하면 많은 데이터를 내장할 것을 권장하고 있다.
- 하지만 이는 모델링적인 측면에서는 맞는 이야기일지 모르지만 성능적인 측면에서는 그렇지 않을 수 있다.
- 많은 데이터를 내장할수록 도큐먼트 하나하나의 크기가 커지고, 그로 인해서 더 많은 디스크 읽이 오퍼레이션이 필요하며, 메모리의 캐시 효율이 떨어진다.
- 7.1.4 뷰(View) : 테이블의 데이터를 가공해서 보여주는 뷰
- 복잡한 형태의 데이터 가공 로직을 캡슐화해서 사용자의 접근 용이성 향상
- 테이블의 일부 데이터에 대해서만 접근 권한을 허용하여 보안 강화
- 7.1.5 BSON 도큐먼트
- 장점
- Lightweight : 각 필드의 값을 단순히 문자열만으로 저장하는 것이 아니라, 정수와 부동 소수점 그리고 날짜 등과 같은 이진(Binary) 데이터 타입을 이용해서 데이터를 저장
- Traversable : BJSON 도큐먼의 각 필드는 항상 필드 값의 데이터 타입과 필드 값의 길이(바이트 수)가 먼저 저장돼 있기 때문에 복잡한 파싱 처리 과정 없이 필요한 필드만 빠르게 찾음
- Effiecient : 기본 데이터 타입으로 C 언어의 프리미티브(원시) 타입을 사용하기 있기 때문에 어떤 개발 언어에서도 매우 빠르게 인코딩 및 디코딩
- 기본 데이터 타입
- BYTE : 일반적인 문자열 데이터를 저장하기 위한 저장 공간
- INT32 : 32비트(4바이트)의 부호를 가지는 정수
- INT64 : 64비트(8바이트)의 부호를 가지는 정수
- DOUBLE : 8바이트 부동 소수점
- 장점
- 7.1.6 제한 사항
- 하나의 도큐먼트는 반드시 "{" 로 시작해서 "}"로 종료
- 도큐먼트의 모든 원소는 반드시 키와 값의 쌍으로 구성돼야 함
- 중첩된 도큐먼트의 깊이는 100레벨까지만 지원
- 도큐먼트의 전체 크기는 16MB까지만 지원
7.2 데이터 타입
- ObjectId : MongoDB의 프라이머리 키인 "_id" 필드의 값으로 자주 사용
- Integer & Double : 저장 공간의 크기에 따라서 32비트와 64비트 정수.
- Decimal : 고정 소수점 데이터를 저장
- String : UTF-8 문자셋을 사용
- Timestamp : 8바이트 저장 공간에 저장. 처음 4바이트는 유닉스 타임스탬프이며 마지막 4바트는 자동으로 시퀀스 값
- 하나의 서버에서 반드시 유일한 값을 보장
- Date : 내부적(BSON)으로 밀리초 단위의 유닉스 타임스템프 값을 64비트 정수로 저장
- MongoDB 서버는 시각 값을 항상 UTC로 변환해서 저장
- 7.2.1 데이터 타입 비교
- 필드 값의 데이터 타입 검색 가능
- ex) db.phone.find( { "phone_nubmer" : { $type : "string" } } );
- 필드 값의 데이터 타입 검색 가능
- 7.2.2 필드 값의 비교 및 정렬
- 한 컬렉션에 있는 각 도큐먼트 필드가 서로 다른 데이터 타입의 값을 가질 수 있다. 이 경우 데이터 타입의 순서로 정렬을 수행
- 7.2.3 문자셋과 콜레이션
- UTF-8 문자셋만 사용 가능
- 기본적으로 각 문자가 가진 문자의 코드(Unicode code Point) 값을 기준으로만 정렬을 수행
- 콜레이션(MongoDB 3.4 이상)
- 문자열 비교에서 사용자가 원하는 언어에 의존적인 규칙을 적용할 수있게 해줌.
- 한글 콜레이션
- 영문보다 한글이 먼저 정렬
- 7.2.4 MongoDB 확장 JSON(Extended JSON)
- JSON 은 MongoDB 서버에서 사용하는 BJSON의 일부 타입만 지원
- STRICT 모드는 외부의 모든 JSON 도구들이 JSON 도큐먼트를 파싱
- Mongo 셸 모드는 Monog 셀이나 mongoimport와 같은 MongoDB의 도구들만 인식
- JSON 은 MongoDB 서버에서 사용하는 BJSON의 일부 타입만 지원
7.3 모델링 고려 사항
- 7.3.1 도큐먼트의 크기
-
큰 컬렉션에서 아주 빈번하게 변경되는 데이터(단순 조회수)만 별도의 컬렉션으로 분리하는 것은 안정적인 서비스를 위해서 고려해볼 만한 부분
- 하나의 컬렉션에서 기능별로 조회되는 부분이 완전히 다르다면 그 데이터들은 다른 컬렉션으로 분리하는 것도 좋은 방법
-
- 7.3.2 정규화와 역정규화(Document Referencing vs. Embedding)
- MongoDB에서 종속적인 정보를 부모 컬렉션에 포함(Embed)하도록 설계하는 이유
- MongoDB는 조인을 지원하지 않음
- MongoDB는 트랜잭션을 지원하지 않음
- 게시물 컬렉션에 모든 댓글을 서브 도큐먼트의 배열 형태로 내장하도록 모델링할 경우 문제점
- 도큐먼트의 크기가 계속 증가하는 문제
- 도큐먼트의 일부 정보에 접근하기 위해서 전체 도큐먼트를 읽고 써야 하는 문제
- 도규먼트에 포함된 게시물과 댓글을 동시에 읽고 쓰는 데 제한되는 문제점
- MongoDB에서 종속적인 정보를 부모 컬렉션에 포함(Embed)하도록 설계하는 이유
- 7.3.3 서브 도큐먼트(Sub Document)
- 각 필드를 성격별로 묶어서 서브 도큐먼트를 생성하는 방법은 도큐먼트의 가독성과 식별성을 높여 주고, 필드의 이름에서 반복된 단어를 생략할 수 있다.
- 7.3.4 배열(Array)
- MongoDB의 배열을 이용하면 RDBMS에서는 불가능한 데이터 모델을 생성 가능
- 하지만 배열의 데이터가 많아지면 MongoDB 서버의 성능적인 문제점을 유발할 수 있음
- 도큐먼트의 크기 증가
- 하나의 도큐먼트는 최대 16M의 데이터를 저장할 수 있음
- 배열 관련 연산자 선택
- $push : 배열의 마지막에 새로운 아이템 추가
- $pop : 배열의 제일 첫 번째 아이템 삭제
- 배열과 복제
- 배열 필드에 2개의 값을 추가했을 뿐인데 MongoDB가 생성한 복제 로그에는 배열의 모든 값이 나열돼 있다. MongoDB 의 처리 성능에 상당한 걸림돌로 작용
- 7.3.5 필드이름
- 필드명의 길이가 길어지면 성능 저하
- 7.3.6 프레그멘테이션(Fragmentation)과 패딩(Padding)
- 도큐먼트 이동 과정이 반복되면 데이터 파일에서 도규먼트 사이에 빈 공간(프레그멘테이션)이 발생
- 프레그멘테이션의 문제점을 보완하기 위해서 패딩(Padding)이라는 기능 도입
- 앞으로 도큐먼트의 크기가 증가할 것을 대비해서 빈 공간을 미리 만들어서 저장
- 7.3.7 도큐먼트 유효성 체크
- 쿼리의 조건절에 사용할 수 있는 대부분의 표현식을 다양하게 필드 단위로 명시
- 7.3.8 조인
- MongoDB 3.2 버전부터는 "$lookup"이라는 보조적인 조인 기능을 제공
- 제약사항
- INNER JOIN은 지원하지 않으며, OUTER JOIN만 지원한다.
- 조인되는 대상 컬렉션은 같은 데이터베이스(DB)에 있어야 한다.
- 샤딩되는 않은 컬렉션만 "$lookup" 오퍼레이션을 사용할 수 있다.
05. 인덱스
5.1 디스크 읽기 방식
- 5.1.1 디스크 저장 매체
- 모든 시스템에서 디스크가 가장 취약함. 쿼리 튜닝의 가장 핵심은 이러한 단점을 보안하기 위해서 쿼리의 작동 방식을 개선하는 것
- 5.1.2 랜덤 I/O와 순차 I/O
- 쿼리를 튜닝한다는 것은 얼마나 랜덤 I/O의 회수를 줄이느냐 즉, 처리에 꼭 필요한 데이터만 읽도록 쿼리를 개선하는 것
5.2 인덱스란?
- 데이터의 저장 성능을 희생해서 상대적으로 데이터의 읽기 속도를 향상시키는 존재
5.3 MongoDB 인덱스의 개요
- 5.3.1 클러스터링 인덱스
- MongoDB의 모든 스토리지 엔진에서 사용되는 인덱스는 클러스터링 인덱스를 지원하지 않음
- 5.3.2 인덱스 내부
- MMAPv1 스토리지 엔진의 Record-Id
- 인덱스 키의 "Record-Id"에 실제 도큐먼트가 저장된 주소(물리적인 주소)를 저장
- WiredTiger 스토리지 엔진의 Record-Id
- MMAPv1 스토리지 엔진과 달리 인덱스 키 엔트리에 논리 주소(도큐먼트마다 고유의 식별자. 자동 증가값)를 사용
- MMAPv1 스토리지 엔진의 Record-Id
- 5.3.3 로컬 인덱스(Local Index)
- MongoDB의 모든 인덱스(프라이머리와 세컨드리 인덱스 모두)는 샤드 단위로 로컬 데이터에 대한 인덱스를 관리
- MongoDB의 인덱스도 다른 RDBMS와 동일하게 쿼리의 성능을 높이는 반면 도큐먼트의 생성 및 변경 처리 성능을 저하시킴
- 5.3.4 인덱스 키 엔트리 자료 구조
- 인덱스의 내부 저장 구조는 도큐먼트나 BJSON 자료 구조를 사용하지 않음
5.4 B-Tree 인덱스
- 5.4.1 구조 및 특성
- 범용적인 목적의 인덱스
- 5.4.2 인덱스 키 추가 및 삭제
- 인덱스 키 추가
- 만약 키 값이 존재하지 않으면 B-Tree의 리프 노드에 인덱스 값을 추가하고 그 하위에 데이터 레코드가 저장된 위치를 저장
- 만약 노드가 꽉 차게 되면 노드를 분리(Split)해야 하는데 이 경우에는 브랜치 노드의 변경이 필요
- 인덱스 키 삭제
- 해당 키 값을 찾아서 그냥 삭제 마크
- 인덱스 키 변경
- 먼저 키 값을 삭제한 다음, 다시 새로운 키 값을 추가하는 형태
- 인덱스 키 검색
- B-Tree의 루트 노드로부터 시작해서 브랜치 노드를 거쳐 최종 리프 노드까지 비교하는 과정을 통해서 이동
- 인덱스 키 추가
- 5.4.3 B-Tree 인덱스 사용에 영향을 미치는 요소
- 인덱스 키 값의 사이즈
- 인덱스 키 값의 사이즈가 작으면 작을수록 좋음
- B-Tree 깊이(Depth)
- 인덱스 키 값의 사이즈가 커지면 커질수록 B-Treed의 깊이(Depth)가 깊어져서 디스크 읽기가 더 많이 필요해 짐
- 선택도(기수성)
- 선택도가 높아야 그만큼 빠른 검색으로 연결
- 읽어야 하는 레코드의 건수
- 인덱스를 통해서 읽어야 할 레코드의 건수가 전체 컬렉션 도큐먼트의 15~20%를 넘어가면 인덱스를 이용하지 않고 컬렉션 스캔(풀 테이블 스캔)으로 필요한 레코드만 가려내는 방식(필터링)으로 처리
- 인덱스 키 값의 사이즈
- 5.4.4 B-Tree 인덱스를 통한 데이터 읽기
- 인덱스 레인지 스캔
- 검색해야 할 인덱스의 범위가 결정된 경우에 사용
- 인덱스 프리픽스(Prefix) 스캔
- 일반적인 레인지 스캔과 동일한 방식으로 작동
- 커버링 인덱스
- 컬렉션의 데이터 파일은 전혀 참조하지 않고 인덱스만 읽어서 커리가 처리되는 최적화
- 인덱스 인터섹션(Intersection)
- 2개 이상의 인덱스 활용. 컬렉션의 인덱스가 최적으로 생성되지 못한 경우에 자주 사용되는 MongoDB의 최적화 방법 중 하나
- 인덱스 풀 스캔
- 쿼리가 인덱스에 명시된 컬럼만으로 조건을 처리할 수 있거나 전체 쿼리를 처리할 수 있는 경우
- 인덱스 레인지 스캔
- 5.4.5 컴파운드 인덱스(compound Index)
- 2개 이상의 필드를 가지는 인덱스. 인덱스 내에서 각 필드의 위치(순서)가 상당히 중요
- MongoDB의 복합 필드 인덱스
- 컴파운드 인덱스를 생성하는 경우에 인덱스를 구성하는 각 필드가 서로 다른 정렬 방식을 가질 수 있음
- MongoDB의 단일 필드와 복합 필드의 기준
- 복합 필드 인덱스는 도큐먼트의 1레벨 뿐만 아니라 서브 도큐먼트의 필드도 포함 할 수 있음
- 복합 인덱스의 장점
- 여러 타입의 인덱스를 혼합해서 결합 가능
- 결합된 필드의 정렬 순서를 변경할 수 있음
- 5.4.6 B-Tree 인덱스의 정렬 및 스캔 방향
- 인덱스의 정렬
- 1은 오름차순. -1은 내림차순 정렬
- 인덱스 스캔의 방향
- 인덱스의 기본 방향은 항상 오름차순으로 구현돼 있지만 이 인덱스를 읽는 방향에 따라서 오름차순 또는 내림차순의 효과를 얻을 수 있다.
- 인덱스의 정렬
- 5.4.7 B-Tree 인덱스의 가용성과 효율성
- 비교 조건의 종류와 효율성
- 컴파운드 인덱스에서 각 필드의 순서와 그 필드에 사용된 조건에 따라서 각 인덱스 필드의 비교 형태가 달라지며, 그 효율 또한 달라짐.
- 인덱스의 가용성
- B-Tree 인덱스의 특징은 왼쪽 값을 기준으로 오른쪽 값이 정렬돼어 있다는 것
- 가용성과 효율성 판단
- 작업 범위 결정으로 사용할 수 없는 경우
- NOT-EQUAL로 비교된 경우("$ne", "$nin")
- 문자열 패턴 검색에서 프리픽스 일치가 아닌 경우
- 문자열 데이터 타입의 콜레이션이 컬렉션이나 인덱스의 콜레이션과 다른 경우
- 작업 범위 결정으로 사용할 수 없는 경우
- 비교 조건의 종류와 효율성
5.5 해시(Hash) 인덱스
해시 샤딩을 구현하기 위해서 꼭 필요한 인덱스
- 5.5.1 해시 인덱스의 구조 및 특성
- 가장 큰 장점은 빠르다는 것
- 5.5.2 해시 인덱스의 가용성 및 효율성
- 키 값 자체가 아니라 해시 함수의 결과값으로 접근해야 하고, 정렬이 보장되지 않는다는 단점
- 해시 인덱스를 이용할 수 있는 형태는 오로지 해당 키 값을 일치와 불일치 비교 연산자로 비교하는 경우
- 크다 또는 작다 기반의 검색은 해시 인덱스를 사용할 수 없음
- 5.5.3 MongoDB 해시 인덱스의 구조 및 특성
- MongDB의 해시 함수는 내부적으로 B-Tree 인덱스의 알고리즘을 사용하므로 검색 성능이 B-Tree 인덱스와 비교해서 차이가 없다.
- 해시 인덱스는 원본값을 그대로 인덱스로 사용하지 않고 해시 된 값의 결과 중에서 8바이트만 인덱스키로 사용하므로 인덱스 필드의 원본의 값이 아무리 길어도 인덱스 키 값이 길이 제한에 걸리지 않는다는 장점
- 5.5.4 MongoDB 해시 인덱스의 제한 사항
- 단일 인덱스에 대해서만 해시 인덱스 생성 가능
5.6 멀티 키 인덱스
멀티 키는 이름 그대로 하나의 도큐먼트가 여러 개의 인덱스 키를 가지는 형태
db.contacts.insert({ name: "matt", addresses:[ { type: "office", address: "경기도 성남시" }, { type: "home", address: "서울시 광진구" } ] }) |
멀티 키 인덱스 생성
db.contacts.createIndex( {"addresses.address" :1 } ) |
- 5.6.1 멀티 키 인덱스의 주의 사항
- 멀티 키 인덱스에 대한 조건은 기존 RDBMS의 BETWEEN과 동일하게 작동하지 않는다. 각 조건을 따로 비교한 다음에 두개의 결과를 병합
- 일반적인 BETWEEN 연산자와 같은 결과를 얻으려면 $elemMatch 연산자를 사용.
- 5.6.2 멀티 키 인덱스의 성능
- 멀티 키 인덱스는 다른 인덱스보다 더 많은 인덱스 키 엔트리를 추가하고 삭제하는 작업을 필요로 함
- 인덱스에 추가하고 삭제해야 할 인덱스 키가 많을 수록 데이터의 변경 성능은 큰 영향을 받는다.
- 5.6.3 멀티 키 인덱스의 제한 사항
- 멀티 키 인덱스는 샤드 키로 사용될 수 없다.
- 해시 알고리즘을 사용하는 인덱스는 멀티 키 인덱스로 정의될 수 없다.
- 멀티 키 인덱스는 커버링 인덱스 처리가 불가능
5.7 전문 검색 인덱스
- 5.7.1 형태소 분석 알고리즘
- 불용어(Stop Word) 처리
- MongoDB 서버는 불용어가 소스 코드에 정의돼 있기 때문에 아직 사용자가 직접 불용어를 추가하거나 삭제 불가
- 형태소 분석(Stemming)
- MongoDB 서버는 Snowball 이라는 오픈 소스를 이용해서 구현. 한국어에 대한 형태소 분석 기능은 구현되어 있지 않음.
- 불용어(Stop Word) 처리
- 5.7.2 N-Gram 알고리즘
- 전문을 무조건으로 몇 글자씩 잘라서 인덱스하는 방법
- 구분자(Delimiter)에 의한 방법보다는 인덱싱 알고리즘이 복잡하고, 만들어진 인덱스의 사이즈도 상당히 큰 편
- MongoDB 3.4버전까지는 n-Gram 인덱스를 지원하지 않음
- 5.7.3 형태소 분석과 N-Gram의 장단점
- 5.7.4 전문 검색 인덱스의 활용
- 전문 검색을 사용하려면 먼저 컬렉션에 전문 검색 인덱스를 생성
-
전문 검색 인덱스 생성
// 필드 레벨의 전문 검색 인덱스 생성
db.articles.createIndex( {title: "text"})
db.articles.createIndex( {title: "text", contents: "text" })
// 컬렉션 레벨의 전문 검색 인덱스 생성
db.articles.createIndex( {"$**": "text"} )
- 중요도(Weight) 할당
- 전문 검색 인덱스는 필드별로 중요도(Weight)를 설정할 수 있음
- 전문 검색 쿼리에서 중요도까지 같이 조회하거나, 중요도를 이용해서 정렬하고자 할 때는 $meta 연산자를 이용
-
mongo> db.scripts.createIndx(
{movie_name: "text", pharse: "text"},
{weights: {movie_name: 2, phrase: 1}, name: "TextIndex"})
// movie_name 필드 일치 시 score 값 확인
mongo> db.scripts.find({$text:{$search:"starwars"}},
{score: { $meta: "textScore" }})
- 컴파운드 인덱스와 인덱스 파티셔닝
- B-Tree 인덱스와만 결합해서 컴파운드 인덱스를 구성
- MongoDB는 아직 한국에 대해서 형태소 분석을 못하기 때문에 거의 문장 기호와 띄워쓰기 단위로 모든 단어가 전문 검색 인덱스에 등록해야 하는 키워드가 됨
- 언어 구분 및 대소문자 처리
- 국가별 언어에 따라서 전문 검색 인덱스 키를 추출하는 알고리즘이 달라짐
- 한국어는 외부 라이브러리(https://docs.mongodb.com/manual/tutorial/text-search-with-rlp/)를 활용. 더 이상 지원하지 않음
- 응용 프로그램에서 먼저 필요한 단어들만 필터링해서 별도의 필드에 저장하고, 그 필드에 대해서 전문 검색 인덱스를 생성하는 것도 좋은 방법
- 전문 인덱스의 한계와 회피
- 응용 프로그램에서 contents의 내용을 직접 주요 키워드 단위로 잘라서 별도의 배열 필드에 저장하고, 이 필드를 멀티 키 인덱스로 생성
- 검색할 때에는 정규 표현식을 이용해서 전방 일치 조건(/^검색어/)을 사용하면 주요 명사 뒤에 붙은 조사는 무시하고 검색을 실행
- 5.7.5 부정 비교와 문장 검색
- 여러 개의 검색어를 동시에 검색 가능
- 검색어에 나열한 단어들은 OR 조합으로 연결돼서 검색
- 검색어를 '\"'로 묶어주면 MongoDB는 내부적으로 구절(phrase)로 해석해서 전문 검색 비교
- 부정 비교 조건은 검색어에 하이픈("-")을 붙여서 "-name" 키워드를 추가
- 5.7.6 MonoDB 전문 검색 인덱스의 버전 호환성
- MongoDB 버전전문 인덱스
2.4 1 2.6 2 3.2 3
- MongoDB 버전전문 인덱스
- 5.7.7 전문 검색 인덱스의 제약 사항
- 전문 인덱스는 컬렉션당 최대 1개만 생성 가능
- 전문 검색 쿼리($text) 가 사용된 쿼리에서는 쿼리 힌트를 사용할 수 없다.
- 쿼리 결과의 정렬은 전문 검색 인덱스를 이용해서 처리할 수 없다.
- 전문 검색 인덱스는 멀티 키 인덱스나 공간 검색 인덱스와 함께 컴파운드 인덱스를 생성할 수 없다.
- 전문 검색 인덱스의 검색은 접두어 일치(Prefix Matching)는 사용할 수 없으며, 항상 전체 일치 검색만 사용 가능
5.8 공간 검색 인덱스
- MongoDB 2.2 버전에서는 유클리드 기하학에 기반을 둔 평면 좌표계를 사용하는 "2d" 인덱스를 제공
- MongoDB 2.4 버전부터는 구면 기하학에 기반을 둔 "2dsphere" 인덱스까지 지원
- 5.8.1 GeoHash 알고리즘
- 세계 지도를 세로로 한번 양분하고 다시 가로로 양분하는 작업을 반복하면서 각 영역의 식별자를 0과 1로 연결해서 GeoHash 코드값을 생성하는 방식

-
- GeoHash 인덱스의 내부 작동
- MongoDB의 공간 인덱스를 사용하지 않고 직접 사용자가 위치를 검색하는 방법.
- 실제 MongoDB의 "2d" 인덱스가 동일한 기능을 MongoDB 내부적으로 구현하고 있고, 검색 기능도 제공하므로 사용하지 않아도 됨
- GeoHash 인덱스의 내부 작동
- 5.8.2 S2 Geometry 알고리즘
- 구글에서 개발한 알고리즘
- 하나의 선(Line)으로 2차원 공간의 모든 구역을 채울 수 있다는 이론
- <레벨별로 힐버트 커브의 구성 방식> upload.wikimedia.org/wikipedia/commons/4/46/Hilbert_curve.gif
- <S2 Geometry가 지구 구체를 커버하는 방식>

- S2 Geometry 인덱스의 내부 작동

-
-
- S2셀을 통해 POI 정보를 정수 값 비교로 찾아낼 수 있음
- MongoDB의 "2dsphere" 인덱스가 S2 Geometry 라이브러리를 어떻게 이용하는지 보여줌
- S2 Geometry의 검색 최적화
- Geometry를 이용하는 공간 인덱스에서 쿼리의 성능에 영향을 미치는 중요한 2가지 요소
- 검색 대상 셀의 최소 레벨과 최대 레벨
- 검색 대상 셀의 개수
- Geometry를 이용하는 공간 인덱스에서 쿼리의 성능에 영향을 미치는 중요한 2가지 요소
-
- 5.8.3 MongoDB의 공간 인덱스
- MongoDB 2.4 버전부터는 공간 데이터를 위해서 GeoJSON 포맷을 사용
-
coordinates 필드는 배열 형태로 항상 경도(longitude)와 위도(latitude) 순서로 배치
GeoJSON 포맷
{ "type": "<GeoJSON Type",
"coordinates": <coordinates>
}
- 5.8.4 MongoDB의 컴파운드 공간 인덱스
- RDMBS 에서는 일반 컬럼(1차원 데이터)과 R-Tree 인덱스를 묶어서 결합 인덱스(컴파운드 인덱스)를 생성할 수 없음
- MongoDB 는 내부적으로 S2 Geometry 라이브러리를 이용해서 2차원 데이터를 1차원 데이터로 변환한 다음 인덱스를 생성하므로 결합 인덱스 생성 가능
- {type:1, loc: "2dsphere"} 순서로 결합 인덱스를 생성했다면 반드시 모든 공간 검색 쿼리는 "type" 필드를 가지고 있어야 함
- 다른 일부 쿼리는 type 필드 조건이 없다면?
- {type:1, loc: "2dsphere"} 인덱스와 {loc: "2dsphere"} 인덱스를 모두 생성
- 컴파운드 인덱스에서 type 필드와 loc 필드의 순서 변경 {loc: "2dsphere", type:1}
- 검색 범위를 좁혀 주는 기능보다는 필터링 조건으로 동작
- 다른 일부 쿼리는 type 필드 조건이 없다면?
5.9 인덱스 속성
- 5.9.1 프라이머리 키와 세컨드리 인덱스
- MongoDB의 프라머리 키 필드는 무조건 "_id" 라는 이름으로 도큐먼트에 저장
- 컬렉션마다 단 하나의 프라이머리 키만 가질 수 있으며, 그 이외의 인덱스는 모두 세컨더리 인덱스
- 5.9.2 유니크 인덱스
- 사실 인덱스라기보다는 제약 조건에 가깝다.
- 유니크 인덱스가 일반 인덱스보다 성능이 빠르다고 생각하는 사용자가 있는데, 이는 사실과 다를때가 휠씬 많음
- INSERT나 UPDATE 그리고 DELETE와 같은 데이터 변경 문장의 처리 성능을 많이 떨어뜨림
- 전문 인덱스나 공간 인덱스는 유니크 속성을 활성화하는 경우에 때때로 의도하지 않은 결과를 만들 수도 있음
- 5.9.3 Partial 인덱스와 Sparse 인덱스
- Spare 인덱스 : NULL 값을 가지는 필드에 대해서 인덱싱할 것인지 선택
- 많은 도큐먼트가 특정 필드를 가지지 않는데, 이 필드를 가지는 도큐먼트만 검색을 실행하는 경우
- Partial 인덱스 : 특정 조건에 따라 인덱스
- Spare 인덱스 : NULL 값을 가지는 필드에 대해서 인덱싱할 것인지 선택
- 5.9.4 TTL 인덱스
- TTL(Time To Live) 인덱스
- 컬렉션의 도큐먼트가 어제까지 유효한지 판단하여 더 이상 유효하지 않은 도큐먼트는 자동으로 삭제되게 하는 기능의 인덱스
- 내부적으로 TTL Monitor라는 쓰레드가 지정된 시간 간격(기본 설정은 매 1분)으로 1회씩
- TTL Monitor 쓰레드의 삭제 주기 변경
-
// TTL Monitor 쓰레드가 10분 단위로 실행되게 설정
mongo > db.adminCommand({setParameter:1, ttlMonitorSleepSecs: 600})
{ "was" : 80, "ok" : 1}
-
재시작해도 새로 설정한 TTL Monitor 쓰레드의 삭제 주기를 적용하고 싶다면 MongoDB 설정 파일 수정
...
setParameter:
ttlMonitorSleepSecs : 30
-
- TTL Monitor의 로그 확인
- 로그의 내용에는 언제 TTL Monitor 쓰레드가 깨어났는지와 얼마나 많은 도큐먼트를 삭제했는지가 출력
- TTL Monitor 쓰레드 정지 및 시작
- TTL Monitor 쓰레드를 멈추는 방법
-
// MongoDB의 시작 옵션으로 TTL Monitor 쓰레드 비활성화
$ mongod --setParameter ttlMonitorEnabled=false;
// 실행 중인 MongoDB의 TTL Monitor 쓰레드 중지
mongod> db.adminCommand({setParameter:1, ttlMonitorEnabled:false});
- 영구적으로 중지하고자 한다면 MongoDB 설정 파일에 다음 내용 추가
-
setParameter:
ttlMonitorEnabled : false
-
- TTL Monitor 쓰레드를 멈추는 방법
- TTL 인덱스와 Partial 인덱스
- TTL 인덱스 또한 다른 인덱스처럼 Partial 인덱스로 생성 가능
- TTL 인덱스와 복제
- 실제 TTL Monitor 쓰레드가 도큐먼트를 삭제하는 작업은 레플리카 셋의 프라이머리 멤버에서만 실행
- TTL 인덱스의 주의사항
- TTL Monitor 쓰레드로 인한 처리 지연은 많은 디스크 읽고 쓰기를 유발하게 되고, 이런 과부하로 복제 지연이 발생할 수 있음
- TTL 인덱스는 반드시 Date 타입의 단일 필드로만 인덱스 생성 가능
- TTL(Time To Live) 인덱스
- 5.9.5 인덱스 콜레이션(대소문자 구분 설정)
- MongoDB 3.2 버전까지는 모든 문자열 비교가 대소문자를 구분하는 Case-Sensitive 방식
- MongoDB 3.4 버전부터는 문자열 값에 대해서 콜레이션 도입
- MonogDB 3.2 에서 대소문자 검색
- MongoDB 3.2 버전까지는 사용자가 입력한 문자열과 검색이나 정렬을 위해서 대소문자를 모두 소문자로 통일한 문자열을 별도로 저장
- 콜레이션과 인덱스 사용
- 콜레이션은 문자열의 정렬과 비교 규칙을 결정
- 쿼리를 실행할 때 인덱스에 콜레이션과 다른 콜레이션을 이용해서 쿼리를 실행하면 인덱스를 활용하지 못하게 됨
- 5.9.6 외래키
- MongoDB는 외래 키에 대한 제약 기능을 지원하지 않음.
'프로그래밍 > MongoDB' 카테고리의 다른 글
MongoDB Docker-compose Replica (0) | 2021.06.25 |
---|---|
[2월 25일] 온라인 세션 'MongoDB University 교육과정과 Certification에 대한 모든 것' (0) | 2021.02.16 |
M320 Data Modeling (0) | 2020.08.05 |
M001 MongoDB Basics (0) | 2020.08.05 |
몽고DB_BACK_TO_THE_BASIC (0) | 2020.08.05 |
신규 프로젝트를 위한 몽고 DB 도입 가이드 (0) | 2020.07.10 |