본문 바로가기

프로그래밍/MongoDB

대용량 데이터 처리를 위한 Real MongoDB

728x90
반응형

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 서버가 지원하지 못하는 한계점

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의 도구들만 인식

7.3  모델링 고려 사항

  • 7.3.1 도큐먼트의 크기
    • 큰 컬렉션에서 아주 빈번하게 변경되는 데이터(단순 조회수)만 별도의 컬렉션으로 분리하는 것은 안정적인 서비스를 위해서 고려해볼 만한 부분

    • 하나의 컬렉션에서 기능별로 조회되는 부분이 완전히 다르다면 그 데이터들은 다른 컬렉션으로 분리하는 것도 좋은 방법
  • 7.3.2 정규화와 역정규화(Document Referencing vs. Embedding)
    • MongoDB에서 종속적인 정보를 부모 컬렉션에 포함(Embed)하도록 설계하는 이유
      • MongoDB는 조인을 지원하지 않음
      • MongoDB는 트랜잭션을 지원하지 않음
    • 게시물 컬렉션에 모든 댓글을 서브 도큐먼트의 배열 형태로 내장하도록 모델링할 경우 문제점
      • 도큐먼트의 크기가 계속 증가하는 문제
      • 도큐먼트의 일부 정보에 접근하기 위해서 전체 도큐먼트를 읽고 써야 하는 문제
      • 도규먼트에 포함된 게시물과 댓글을 동시에 읽고 쓰는 데 제한되는 문제점
  • 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 스토리지 엔진과 달리 인덱스 키 엔트리에 논리 주소(도큐먼트마다 고유의 식별자. 자동 증가값)를 사용
  • 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 이라는 오픈 소스를 이용해서 구현. 한국어에 대한 형태소 분석 기능은 구현되어 있지 않음.
  • 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
  • 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 내부적으로 구현하고 있고, 검색 기능도 제공하므로 사용하지 않아도 됨
  • 5.8.2 S2 Geometry 알고리즘
  • <S2 Geometry가 지구 구체를 커버하는 방식>

  • S2 Geometry 인덱스의 내부 작동

      • S2셀을 통해 POI 정보를 정수 값 비교로 찾아낼 수 있음
      • MongoDB의 "2dsphere" 인덱스가 S2 Geometry 라이브러리를 어떻게 이용하는지 보여줌
    • S2 Geometry의 검색 최적화
      • 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} 
          • 검색 범위를 좁혀 주는 기능보다는 필터링 조건으로 동작

5.9 인덱스 속성

  • 5.9.1 프라이머리 키와 세컨드리 인덱스
    • MongoDB의 프라머리 키 필드는 무조건 "_id" 라는 이름으로 도큐먼트에 저장
    • 컬렉션마다 단 하나의 프라이머리 키만 가질 수 있으며, 그 이외의 인덱스는 모두 세컨더리 인덱스
  • 5.9.2 유니크 인덱스
    • 사실 인덱스라기보다는 제약 조건에 가깝다.
    • 유니크 인덱스가 일반 인덱스보다 성능이 빠르다고 생각하는 사용자가 있는데, 이는 사실과 다를때가 휠씬 많음
      • INSERT나 UPDATE 그리고 DELETE와 같은 데이터 변경 문장의 처리 성능을 많이 떨어뜨림
    • 전문 인덱스나 공간 인덱스는 유니크 속성을 활성화하는 경우에 때때로 의도하지 않은 결과를 만들 수도 있음
  • 5.9.3 Partial 인덱스와 Sparse 인덱스
    • Spare 인덱스 : NULL 값을 가지는 필드에 대해서 인덱싱할 것인지 선택
      • 많은 도큐먼트가 특정 필드를 가지지 않는데, 이 필드를 가지는 도큐먼트만 검색을 실행하는 경우
    • Partial 인덱스 : 특정 조건에 따라 인덱스
  • 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 인덱스와 Partial 인덱스
      • TTL 인덱스 또한 다른 인덱스처럼 Partial 인덱스로 생성 가능
    • TTL 인덱스와 복제
      • 실제 TTL Monitor 쓰레드가 도큐먼트를 삭제하는 작업은 레플리카 셋의 프라이머리 멤버에서만 실행
    • TTL 인덱스의 주의사항
      • TTL Monitor 쓰레드로 인한 처리 지연은 많은 디스크 읽고 쓰기를 유발하게 되고, 이런 과부하로 복제 지연이 발생할 수 있음
      • TTL 인덱스는 반드시 Date 타입의 단일 필드로만 인덱스 생성 가능
  • 5.9.5 인덱스 콜레이션(대소문자 구분 설정)
    • MongoDB 3.2 버전까지는 모든 문자열 비교가 대소문자를 구분하는 Case-Sensitive 방식
    • MongoDB 3.4 버전부터는 문자열 값에 대해서 콜레이션 도입
    • MonogDB 3.2 에서 대소문자 검색
      • MongoDB 3.2 버전까지는 사용자가 입력한 문자열과 검색이나 정렬을 위해서 대소문자를 모두 소문자로 통일한 문자열을 별도로 저장
    • 콜레이션과 인덱스 사용
      • 콜레이션은 문자열의 정렬과 비교 규칙을 결정
      • 쿼리를 실행할 때 인덱스에 콜레이션과 다른 콜레이션을 이용해서 쿼리를 실행하면 인덱스를 활용하지 못하게 됨
  • 5.9.6 외래키 
    • MongoDB는 외래 키에 대한 제약 기능을 지원하지 않음.
728x90
반응형