몽고디비를 사용하여 어플리케이션을 개발할 때 유용한 정보를 알아보자
-
데이터 타입
- 네임 스페이스: 데이터베이스와 컬렉션의 이름 조합. EX) database.collection 으로 표현된다
- 컬렉션: RDBMS에서 테이블이라고 부르는 객체
- 뷰: RDBMS와 동일한 목적으로 뷰를 생성 할 수 있다
- 타입이 서로 다른 필드에 대해 정렬할 경우 필드값의 우선순위로 정렬한다
- BSON 도큐먼트
- JSON 을 바이너리 포맷으로 인코딩한 문서
- JSON 보다 가볍고, 탐색이 가능하며 효율적이다
- 데이터 타입은 Byte, Int 32/64, double을 사용한다
- 제약 사항
- 문서는 반드시 Object로 시작해야 한다 → 배열로 시작 불가
- 중첩된 문서 깊이는 100까지 지원
- 문서의 최대 크기는 16MB
- 종류
- ObjectId
- 12Byte의 바이너리 타입.
_id 인 프라이머리 키에 사용된다
- Interger & Double: 일반적인 숫자형 데이터 타입
- Decimal: 고정 소수점 숫자 데이터 타입
- String: UTF-8 문자셋을 사용하는 문자형 데이터 타입
- Timestamp: 쓰지 말자. 내부적으로 사용되는 값이다
- Date: 밀리초 단위의 유닉스 타입스탬프 값을 64비트로 저장하는 날짜형 데이터 타입
- ISODate()는 UTC를, new Date() 함수는 타임존을 참조한다
- 콜레이션
- 문자열 비교에서 사용자가 원하는 언어에 의존적인 규칙을 적용 가능하게 함
- 다양한 정렬 옵션(caseFirst, numericOrdering) 등을 지정할 수 있다
- 한글 콜레이션을 사용하면 영문보다 한글이 먼저 정렬된다 →
unihan이 가장 상식적이다
- 고려 사항
- 서브 도큐먼트는 필드를 선별하여 필요한 것만 가져가도록 하자
- 조인을 강력하게 지원하지 않기 때문에 적은 양의 종속적인 정보는 부모 컬렉션에서 저장하는 것이 좋다
- 필드를 성격(컨텍스트) 별로 묶어서 서브 도큐먼트를 만드는 것이 가독성이 좋다
- 도큐먼트의 유효성 규칙을 추가하거나 삭제 할 수 있다
-
인덱스
- 인덱스는 일반적으로 데이터의 저장 성능을 희생하여 읽기 성능을 높이는 방법
- 몽고DB는 NoSql이지만 사실상 스키마-프리가 아니다
- 인덱스의 키 값은 모두 정렬되어 있으나 레코드는 정렬되어 있지 않다 → 클러스터링이 아님
- 인덱스의 이름은 변경 할 수 없다
- 일반적인 B-Tree 인덱스를 사용한다
- 외래키를 지원하지 않는다
- 기수성(Cardinality)가 높아야 빠른 검색으로 연결된다
- Record-Id
- 내부적으로 각 문서마다 부여되는 Auto-Incresement 형태의 키 값
- 이 ID를 키로 하여 내부적으로 클러스터링 인덱스를 생성하여 실제 문서와 맵핑한다
- 인덱스를 사용하지 못하는 경우
- Right-Most( ex: like ‘%xxxx’), 부정 연산자(not eq/in), 변형된 컬럼은 인덱스를 사용할 수 없다
- 전체 컬렉션의 15~20%가 넘어가면 옵티마이져가 풀 스캔을 유도한다
- 쿼리/컬렉션/인덱스의 콜레이션이 서로 다른 경우 → 당연히 일치시키는 것이 좋다
- 인덱스 속성
- 프라이머리 키
- 컬렉션에 단 한 개만 존재하는 유니크 인덱스
- 반드시 존재해야 하며
_id 로 생성하거나, 강제로 생성된다
- 세컨더리 인덱스
- 프라이머리 키 외에 유저가 생성하는 인덱스
- 유니크 속성이 지정된 경우 NULL인 도큐먼트는 한 개만 가능하다 → Mysql과 다름
- 샤딩된 경우 프라이머리 인덱스나 유니크 인덱스는 반드시 샤드 키를 포함해야 한다
- Partial 인덱스
- 조건부 인덱싱
- 인덱스를 사용하기 위해서는 인덱싱의 조건이 쿼리에 포함되어야 한다
- TTL 인덱스
- 유효 시간을 설정하고 유효시간이 지나면 문서가 삭제되는 인덱스
- Date 타입의 단일 필드만 가능하다
- 인덱스 종류
- 커버링 인덱스: 인덱스만 읽어서 처리 가능한 쿼리일 때 사용된다
- 클러스터링 인덱스
- 인덱스의 키 값 순서대로 디스크에 저장하는 인덱스
- 레인지 스캔에 매우 빠르나 현재 지원되지 않는다
- 로컬 인덱스
- 모든 인덱스는 샤드 단위로 로컬 데이터의 인덱스를 관리한다
- 인터섹션 인덱스
- 두 개의 인덱스를 사용하여 집합을 찾고 두 개의 교집합을 찾는 쿼리
- 주로 인덱스가 최적이지 않을 때 발생할 확률이 높은 쿼리이다
- 컴파운드 인덱스
- 여러 개의 필드로 이루어진 인덱스
- 각 필드의 순서가 매우 중요하다
- 해시 인덱스
- 단일 검색에 최적화 되어 있음
- B-tree와 달리 최종 리프 노드로 이동해야 하는 Index Look-Up 과정이 없다
- MD5 해시를 통한 값을 8바이트 정수로 변환하여 키의 길이가 작다
- 멀티 키(컬럼) 인덱스
- 여러 개의 인덱스 키가 단 한 개의 도큐먼트를 가르키는 인덱스
- 서브 도큐먼트 배열에 대한 인덱스를 지원하기 위해 사용된다
- Between 을 구현하기 위해서는
$elemMatch 연산자를 이용해야 한다
- 제약
- 샤드 키로 이용 될 수 없다
- 해시 인덱스를 사용할 수 없다
- 커버링 인덱스 처리가 불가능하다
- 공간 검색 인덱스
-
락
-
Wired Tiger 트랜잭션
-
쿼리문
-
실행 계획 및 쿼리 튜닝
-
보안 및 유저
- 작업 범위 결정 조건: 인덱스를 통해 작업의 읽는 범위가 결정되는 쿼리의 조건
- 필터링(체크) 조건: 읽는 범위를 제한하지 못하고 레코드를 필터링해야 하는 쿼리의 조건
- 저자는 인덱싱의 올바른 사용을 위해 필드의 데이터 타입과 일치시켜야 좋다고 설명했다