HDFS Architecture Guide

by Dhruba Borthakur

1. Introduction

분산 파일 시스템. 기존 시스템과의 차이점 : highly falut-tolerant , 저가 하드웨어에 디플로이 가능.
HDFS 는 Apache Nutch web search engine project 의 인프라로 만들어짐.
Apache Hadoop subproject.

2. Assumptions and Goals

2.1 Hardware Failure

하드 페일은 예외라기 보다는 ‘표준’ 이다. HDFS 인스턴스는 수백, 수천의 서버로 구성되어 파일 시스템의 데이터를 저장한다.
많은 수의 컴퍼넌트가 있다는 사실, 각 컴퍼넌트가 non-trivial 한 실패 가능이 있다는 것은 HDFS 의 일부 컴퍼넌트가 항상 non-functional 있다는 것을 의미한다.
그러므로, 결함의 발견과 그것의 빠르고, 자동적인 복구는 HDFS 의 코어 설계 목적이다.

2.2 Streaming Data Access

HDFS 에서 도는 어플은 자신의 데이터 셑에 접근하는 스트리밍이 필요하다. 그것들은 일반 파일 시스템에서 도는 일반 목적의 어플이 아니다.
HDFS 는 일반 유저 사용이 아니라 배칭 프로세싱에 더 알맞게 설계되었다. 데이터 억세스의 낮은 레이턴시보다 high throughtput of data access 에 집중.
Posix 는 HDFS 에 타게팅된 어플에 필요없는 많은 요구조건을 강요하고 있다.
Posix 의 몇몇 키 영역에서의 의미론은 데이터 처리율을 높이는 데 상쇄되었다.

2.3 Large Data Sets

HDFS 에서 도는 프로그램은 기가 / 테라 바이트의 파일.  그러므로, HDFS는 큰 파일을 지원하도록 튜닝 되었음.
싱글 클러스터에서 높은 최종 데이터 밴드위스 와 수백개의 노드를 지원해야 함. 한 인스턴스에서 수천만개의 파일을 지원해야 함.

2.4 Simple Coherency Model

파일에 대해 “1회 쓰고 – 여러번 읽기” 모델 이 필요. 파일이 생성, 기록, 닫히면 변경이 불필요하다. 이 가정은 데이터 일관성 이슈를 간단히 하고, 높은 데이터 억세스 생산량을 가능케 한다. 맵 리듀스나 웹 크롤러는 이 모델에 완벽히 맞아 떨어진다.
향후 추가-기록 을 지원하는 계획이 있음.

2.5 “Moving Computation is Cheaper than Moving Data”

어플의 요청에 의한 계산은 자료가 가까이에 있으면 효율적이다. 특히, 이것은 데이터가 클때 그렇다. 이것은 네트워크 사용을 최소화하고 시스템 성능을 증가시킨다. 가정은 이렇다. 데이터 가까이 컴퓨테이션을 이동하는 게 데이터를 이동하는 것보다 종종 낫다는…
HDFS 는 이렇게 데이터 가까이 어플리케이션을 가까이 가져가는 인터페이스를 제공한다.

2.6 Portability Across Heterogeneous Hardware and Software Platforms

플랫폼 간 이동이 쉽다.

3. NameNode and DataNodes

HDFS 는 마스터/슬레이브 아키텍쳐.
한개의 네임노드 (마스터 서버) +  여러개의 데이터 노드(보통 클러스터에서 노드당 한개), 노드에 붙은 스토리지 관리.
HDFS는 파일 시스템 namespace 를 노출하여 유저 데이터가 파일에 저장되도록 허용함.
내부적으로 한 파일은 하나이상의 블럭으로 나뉘고 이 블럭들은 데이터 노드들의 세트에 저장.
> 네임노드는 file system namespace operation 을 파일이나 폴더를 열고/닫고/리네임 하듯 함.
또한, 데이터노드에 블럭을 매핑하는 결정을 한다.
> 데이터 노드는 클라이언트로부터의 읽기/쓰기 요청에 대응할 책임이 있음.
데이터 노드는 블락생성/삭제/복제 등을 수행.

이 노드들은 머신에서 돌도록 설계된 소프트웨어의 일부임. 이 머신들은 GNU/Linux .. 보통.
자바로 쓰여짐. 자바를 지원하면 노드들을 돌릴 수 있음. 자바가 포터블성이 좋으므로 여러 머신에서 동작 가능.
전형적인 디플로이는 전적으로 네임노드 소트트웨어를 돌림. 각각의 다른 머신은 한 데이터노드를 돌림.
여러 노드를 한 머신에서 돌리는 것이 구조상 가능하지만 실제로는 적다.

네임노드가 하나인 것은 구조를 간단히 해준다. 이 네임노드는 메타데이터 등을 담는 중재자 역할.
유저 데이터는 네임노드를 통해 ‘절대’ 흐르지 않음.

4. The File System Namespace

기존 파일 구성 체계 지원. 디렉토리 생성 가능.  파일을 생성, 이동, 리네임 등 기존 체계와 비슷.
하지만 유저 쿼타를 구현하지 않음. 하드/소프트 링크 지원 안함.  하지만, HDFS 아키텍춰는 이런 구현을 배제하지는 않음.

네임노드는 파일 시스템 네임스페이스를 유지한다. 파일 시스템 네임공간의 변화는 네임노드에 의해 기록된다. 어플이 복제의 수를 규정. 파일의 복제 갯수는 그 파일의 replication factor 라고 함.  이 정보는 네임노드에 저장됨.

5. Data Replication

HDFS 는 큰 클러스터에 큰 파일을 여러 머신에 안정적으로 저장하게 설계되어 있음. 블락의 연속으로 파일 저장 ;
마지막 블락을 제외한 모든 블락은 같은 크기.
파일의 블락은 fault tolerance 를 위해 복제됨. 블락 크기와 복제팩터은 파일 별로 조절 가능. 어플리케이션이 파일의 복제수를 규정.
복제팩터는 파일 생성시에 규정 가능하고 나중에 바뀔 수 있다.
파일은 한번-쓰고 항상 한 writer 를 갖는다.

네임노드는 모든 블락의 복제에 관해 결정을 내림. 주기적으로 핫빝과 블락 레포트를 데이터노드로 부터 받음.
핫빝의 영수증은 잘 기능한다는 걸 의미.
레포트는 데이터노드의 모든 블락의 리스트를 포함함.

5.1 Replica Placement : The First Baby Steps

복제는 신뢰성/성능에 매우 중요.  복제 최적화는 HDFS의 차별화 요소. 또한 튜닝과 경험 필요.
랙 인식 복제의 목적은 데이터 신뢰성, 가용성, 밴드폭 활용을 향상시키기 위함.
현재 복제 정책의 구현은 이 방향의 첫번째 노력이다. 단기 목표는 제품 시스템에서 검증, 행동 연구, 더 복잡한 정책 연구 등이다.

대규모 HDFS 인스턴스는 여러 랙에 걸쳐 분산된다. 다른 랙의 두 노드사이의 통신은 스위치를 통해야 한다. 대부분의 경우 같은 랙 머신간의 네트웤 밴드폭은 다른 랙 사이보다 크다.

네임노드는 각 데이터노드가 속한 랙 아이디를 ‘하둡 랙 인지(Awareness)’ 에서 정하는 프로세스에 따라 결정한다.
간단하지만 최적은 아닌 정책이 복제를 유니크한 랙에 둔다.
이것은 랙 전체가 페일날 때 데이터 유실을 예방하고 데이터 읽기작업에 여러 랙으로부터의 밴드폭을 허용한다.
이 정책은 복제를 골고루 분산시켜 콤포넌트 실패에 로드 발란스를 쉽게 한다. 하지만, 이 방법은 쓰기작업이 여러 랙에 블락을 옮기는 것을 막아야하기 때문에 쓰기 비용을 늘린다.

일반적인 경우 복제계수가 3이면 HDFS의 원칙은 하나를 로컬랙의 한 노드에 놓고, 다른 건 다른 랙의 노드에, 세번째는 다른 랙의 다른 노드에 놓는다.
랙 페일의 가능성은 노드 페일보다 훨씬 적다. 이 원칙은 데이터 신뢰도와 가응성을 해치지 않는다.
하지만, 3개가 아닌 2 랙에 분리되어 있어 데이터 읽을 때의 밴드폭은 줄여준다. 또한, 랙에 골고루 분산시키지는 않는다.
이 원칙은 데이터 신뢰성과 읽기 성능을 떨어뜨리지 않으면서 쓰기 퍼포먼스를 향상시킨다.

여기서 기술된 현재의 디폴트 원칙은 진행 중임.

5.2 Replica Selection

글로벌 밴드폭 소비와 읽기 레이턴시를 최소화하기 위해 HDFS 는 리더에 가장 가까운 복제본으로부터 읽어야 한다?.
리더 노드와 같은 랙에 복제본이 있으면 그놈이 읽기 요청을 만족하는 것이 바람직함. 클러스터가 여러 데이터 센터로 펼쳐지면 로컬 데이터센터에 있는 복제본은 어느 원격 복제본보다 우선된다.

5.3 Safe Mode

시작 시 네임노드는 ‘안전 모드’ 로 들어간다. 이때 복제 작업 없음. 네임노드가 Heartbeat & Blockreport 메시지를 데이터노드로부터 받는다. 블락레포트는 한 데이터노드가 호스팅하는 블록들의 리스트를 담고 있다. 각 블럭은 복제본의 정해진 최소 수를 갖고 있다.
블락은 네임노드에 최소개수가 체크인하면 안전하게  복제됐다고 간주된다. 안전하게 복제된 복제본의 일정 퍼센트가 체크인하고 (추가 30초 ) 후에 안전모드에서 나온다. 그리고나서 정해진 숫자 이하의 블락을 갖는 데이터블록을 결정한다.
그리고나서 네임노드는 이 블락을 데이터노드에 복제한다.

6. The Persistence of File System Metadata

HDFS namespace 는 네임노드에 의해 저장된다.
네임노드는 현재 파일 시스템 메타데이터의 변화를 끊임없이 기록하기 위해 EditLog라 불리는 트랜잭션 로그를 사용한다.
예를 들어 새로운 파일을 생성할 때 네임노드는 이것을 가리키는 에딧로그에 레코드를 삽입한다. 복제 팩터를 바꾸는 것도 비슷.
네임노드는 수정로그 저장에 로컬 호스트 OS 파일 시스템을 이용한다.
파일 블록의 맵핑을 포함한 파일 시스템 이름공간 전체는 FsImage 라는 파일에 저장된다.
이 파일 역시 네임노드의 로컬 파일 시스템에 파일로 저장된다.

네임노드는 전체 파일 시스템 이름공간의 이미지와 파일 블록맵을 ‘메모리’에 띄운다. 이 키 메타데이터 아이템은 작게 설계되어 4기가의 램도 충분하다.
네임노드가 기동할 때 FsImage 와 EditLog 를 디스크에서 읽고 EditLog로 부터의 모든 트랜잭션을 FsImage의 인-메모리 객체에 적용하고 이 새로운 버전을 디스크의 새로운 FsImage 로 플러시아웃 한다.
그리고나서 기존의 EditLog 를 (반영이 되었으므로) 없앤다.
이 과정을 ‘체크포인트’ 라고 한다.
현재 구현에서는 체크포인트는 네임노드가 기동할 때만 일어난다. 향후에는 주기적으로 할 계획이다.

데이터 노드는 HDFS 데이터를 로컬 파일시스템에 저장한다. 데이터노드는  HDFS 에 대해 모른다.
단지 파일의 블럭을 로컬 파일 시스템에 저장할 뿐이다. 모든 파일을 같은 디렉토리에 생성하지 않는다. 대신, ‘자기발견 heuristic’ 을 사용하여 디렉토리당 최적의 파일 수를 결정하고 적당히 하위 디렉토리를 만든다. 모든 파일을 같은 디렉토리에 놓는 것은 적합하지 않다. (파일 시스템 문제)
데이터노드가 기동시 로컬 파일 시스템을 스캔하고 데이터 블록의 리스트를 만들고 이 레포트를 네임노드에 보낸다.
이것은 ‘블럭 레포트’ 이다.

7. The Communication Protocols

모든 HDFS 통신은 TCP/IP 위에 놓여진다. 클라이언트는 네임노드 머신위에 TCP 포트 연결을 확보하여 네임노드와 ClientProtocol 을 통신한다.
데이터노드는 네임노드와 ‘데이터노드 프로토콜’ 을 이용하여 소통한다.
RPC (remote procedure call) 추상화는 클라이언트 / 데이터노드 프로토콜 양쪽을 랩핑한다.
설계상, 네임노드는 어떤 RPC 도 초기화하지 않는다. 대신 데이터노드나 클라이언트에 의해 요청된 RPC 에 응답할 뿐.

8. Robustness

HDFS 의 주된 목적은 실패가 나더라도 데이터를 안정적으로 저장하는 것.
3가지 실패.

8.1 Data Disk Failure, Hearbeats and Re-Replication

각 데이터노드는 네임노드에게 핫빗 메시지를 주기적으로 보냄. 네트워크 파티션은 데이터노드의 섭셋이 네임노드와 연결을 잃게 할 수 있다. 네임노드는 최근에 핫빗을 안 보낸 데이터노드를 죽은 것으로 간주하고 더 이상의 IO 를 보내지 않는다. 죽은 노드에 기록된 데이터는 HDFS 에서 접근할 수 없다. 데이터노드의 죽음은 블럭의 복제 팩터가 내려가게 한다. 네임노드는 끊임없이 어떤 블락이 복제가 필요한 지 추적한다.
재-복제의 필요성이 여러 이유에 의해 제기된다 : 데이터노드가 접근불가,
복제본이 상한경우, 하드 디스크 페일 또는 복제 팩터 증가.

8.2 Cluster Rebalancing

HDFS 구조는 데이터 재균형 계획과 호환됨. 이것은 데이터노드의 빈 공간이 어느 레벨 이하로 내려가면 자동으로 다른 데이터노드로부터 옮겨온다.  어떤 파일에 대해 갑자기 높은 요구가 생기면 스킴은 동적으로 추가의 복제를 생성하고 클러스터의 다른 데이터와 재-균형할 수 있다.
이런 재균형은 아직 ‘미 구 현’ ..

8.3 Data Integrity

데이터노드로부터 가져온 블락이 손상되었을 가능성이 있다.  원인은 스토리지 이상, 네트워크 부실, 소프트웨어 버그.
클라이언트는 첵섬을 구현한다.
클라이언트가 HDFS 파일을 생성하면 각 블럭의 첵섬을 계산하여 HDFS 네임 공간에 히든 파일로 저장한다.
클라이언트가 데이터를 받을 때 확인.
틀리면 그 블럭을 다른 복제본에서 가져온다.

8.4 Metadata Disk Failure

FsImage & EditLog 는 중앙 데이터 구조임. 이 파일이 망가지면 HDFS 인스턴스가 기능 정지하게 됨.
이런 이유로 네임노드는 이 파일들을 여러 카피 유지하도록 함.
이 파일이 수정되면 각각의 복사본이 싱크되게 함.
이런 싱크 작업은 초당 트랜잭션 정도를 줄일 수 있다.
하지만, 메타데이터가 큰 것은 아니기 때문에 이런 성능저하는 수용할 만 하다.
네임노드가 재 시작할 때 최근의 파일들을 이용한다.

HDFS 클러스터에서는 네임노드 머신이 페일나는 한 지점이다. 네임노드가 페일나면 매뉴얼 작업이 필요하다.
현재, 자동 재시작과 네임노드의 페일오버시 다른 머신으로 이전은 지원되지 않는다.

8.5 Snapshots

특정 시간의 데이터의 카피 저장을 지원.  쓰임은 타임머쉰.. 에러 나기 전 시간으로 되돌림.  향후 기능.

9. Data Organization

9.1 Data Blocks

HDFS 는 큰 파일을 지원하기 위해 설계 되었음. 호환되는 어플은 큰 데이터 세트를 다룬다.
이 어플들은 데이터를 한번 쓰지만 한번 이상 읽고 이러한 읽기는 스트리밍 속도를 만족하는 것이 필요하다.
HDFS는 1번쓰고 여러번 읽는 개념을 지원한다. 전형적인 블럭 사이즈는 64 메가 바이트.
그러므로 64씩 잘라지고 다른 데이터 노드에 자리잡는다.

9.2 Staging

파일을 생성하라는 클라이언트 요청은 네임노드에 즉시 닿지 않는다.
실제로, 초기에 HDFS 클라이언트는 파일 데이터를 임시 로컬 파일에 캐시한다.
어플 쓰기는 이 임시 로컬 파일에 투명하게 redirect 된다.
로컬 파일이 블럭 사이즈만큼 데이터를 쌓게 되면 클라이언트는 네임노드에 컨택한다.
네임노드는 파일 이름을 파일시스템 위계에 넣고 데이터블럭을 잡는다.
클라이언트 요청에  네임노드는 데이터노드의 아이디와 최종 데이터 블록을 갖고 응답한다. 그리고나서 클라이언트는 임시파일에서 데이터 블럭을 지운다.
파일이 닫히면, 남은 데이터는 데이터노드로 옮겨진다. 그리고, 클라이언트는 네임노드에 파일이 닫혔다고 한다.
이때, 네임노드는 영구 공간에 파일생성 작업을 커밋한다.
파일이 닫히기전에 네임노드가 죽으면 파일은 잃어버린다.

위의 접근방식은 어플의 특성을 고려하여 세심히 설계 되었다. 이 어플들은 파일에 대해 스트리밍 쓰기가 필요하다. 클라이언트가 클라이언트 측 버퍼링 없이 원격파일에 직접 쓰면 네트워크 속도와 congestion in the network 는 작업에 상당히 영향을 준다.
이 접근은 선례가 없지 않다.  초기의 분산 파일 시스템은 성능을 향상시키기 위해 클라이언트 캐싱을 이용했다.
POSIX 요구는 더 높은 성능을 위해 relaxed ..

9.3 Replication Pipelining

클라이언트가 파일을 쓸 때 로컬 파일에 먼저 쓴다.
복제 계수가 3일 때를 가정.
로컬 파일이 데이터로 가득 차면, 클라이언트는 네임노드로 부터 데이터노드 리스트를 갱신한다.
이 리스트는 그 블록의 복제물을 보관할 데이터노드를 갖고 있다.
그럼 클라이언트는 그 블록을 첫번째 데이터노드에 플러시 한다.
첫번째 데이터노드는 데이터를 작은 조각(4KB)으로 받기 시작해서 로컬 저장소에 쓰면서 그 부분을 두번째 데이터노드에 전달한다.
두번째 노드는 똑같이 세번째 노드에 전달한다.
마침내 세번째 노드가 저장소에 보관한다.
데이터 노드는 파이프라인의 이전 노드에서 데이터를 받고 다음 노드로 넘겨준다.
그러므로 데이터는 한 데이터 노드에서 다음으로 파이프라인 된다.

10 Accessability

HDFS 는 어플에서 여러가지 방법으로 접근 가능하다.  네이티브는 자바 API 제공.
이것에 대한 C 래퍼 또한 가능.   HTTP 브라우저 가능.
WebDAV 프로토콜을 통하는 방법은 개발 중.

10.1 FS Shell

HDFS 는 사용자 데이터를 파일/ 디렉토리로 구성한다. 사용자 인터페이스를 위해 쉘 제공.
다른 쉘과 비슷.
스크립트 언어 지원 위해 필요.

10.2 DFSAdmin

Command set..  HDFS cluster 관리용
관리자 만의 용도.

10.3 Browser Interface

전형적인 HDFS 설치는 TCP 포트를 통한  ‘네임스페이스’를 노출시키는 웹서버를 구성한다.
이것을 통해 브라우징 하면서 내용을 확인할 수 있다.

11. Space Reclamation

11. 1 File Deletes and Undeletes

어플이나 사용자에 의해 파일이 삭제되면 바로 삭제 되지 않음.
휴지통으로 이동.
이동한 파일은 정해진 시간만큼 존재.
완전히 삭제된 후 네임노드는 HDFS 이름공간에서 파일을 삭제.
파일의 삭제는 그에 할당된 블락들을 해제시킴.
파일의 삭제와 빈공간의 증가 사이에는 시간 차이가 존재함.

파일이 휴지통에 있는 동안은 복구 가능.
복구하려면 휴지통으로 가서 복구 해야 함. 여기에는 최종본만 있음.
복구하는 규칙 :: 현재의 정책은 6시간 이상 경과한 파일을 지우는 것.
향후에는 여러 옵션을 적용할 수 있을 것이다.

11.2 Decrease Replication Factor

복제 계수가 줄어들면 네임노드가 지워질 여분의 복제분을 선택한다.
다음번의 핫빗 이 이 정보를 데이터노드에 전달.
데이터 노드가 블럭을 지우고 자유 공간이 증가.  역시 시간차이가 존재.

 

 

In Memory DB ..

2007년 글이지만 참고할 만한 글..

메모리 디비는 ‘소프트웨어’ 이다.
디비 ‘전체’ 를 메모리에 올린다.
‘질의 처리기’
‘동시성 제어 기술’

동시성 제어 기술

동시성 제어 기법은 기존의 “열 단위 잠금(row locking)” 방식의 단점으로 지적돼 왔던 수정된 데이터(updating data)에 대해 장기간 동안 연산이 대기하는 문제점을 해결하는 기술이다.
다중 버전 기법 : MVCC // Multi-Version Concurrency Control
Hot Backup : 디비를 종료하지 않고 즉시 백업..

다중 사용자 처리 기술

시스템 용량과 ‘정비례’ 하지는 않는다.  사용자 수 만큼의 프로세스.. 자원 낭비.  => 쓰레드 기반 아키텍처로 가는 추세. 확장성의 문제..
==> 풀  사용…

질의 최적화 기술

CPU, Cache .. L1, L2 ..

어플라이언스 / 인메모리 

어플라이언스 : 하드웨어와 최적화. 오라클.

인메모리 : SAP  (여기서는 메인 메모리.. DRAM ) 속도가 빠름.. 100배에서 10만배 빨라짐.

몽고 디비 MongoDB The Definitive Guide.. Ch. 4 : Querying

1. Introduction to find [p45]

> db.user.find () >> 컬렉션의 모든 값.
> db.user.find({“username: : “joe”, “age” : 27}) > And 조건절이 됨.

Specifying Which Keys to Return

두번째 인자에 받고 싶은 키를 전달.. 통신량과 일을 줄임. 아이디 키는 항상 리턴.
> db.users.find({}, {“username” : 1, “email” : 1})
키를 제외시킬 때는 0 전달. 아이디를 제외하는 것도 가능.
> db.users.find({}, {“username” : 1, “_id” : 0})

Limitations

쿼리는 상수여야 함. (코드의 일반 변수) 즉, 다큐먼트의 다른 키의 밸류값을 가질 수 없음.
이런 쿼리는 $where Queries … 에서 설명.

2. Query Criteria

보다 다양한 조건. range, or clauses, negation .

Query Conditionals [p47]

“$lt” “$lte” “$gt” “$gte”   “$ne” not equal.  (ne : 모든 타입에 적용 가능)
> start = new Date(“03/04/2007”)
> db.users.find({“registered” : {“$lt” : start}})

OR Queries

“$in” “$or” “$nin”

> db.raffle.find({“ticketNo” : {“$in” : [725, 23, 39]}})
> db.users.find({“user_id” : {“$in” : [345, “steve”]}}) >> 스키마를 변경했을 때 여러 타입 혼용 가능.

“$in” 은 단일 키에서 OR 쿼리 가능. 여러 키를 대상으로는 “$or” 필요.

$not

meta conditional  >> 제외시킬 때.

Rules for Conditionals

조건식은 ‘내부 다큐’, 업데이트 문은 ‘외부 다큐’.
조건식은 단일키에 여러번 적용가능.. 업데이트문은 한번만 가능.

3. Type-Specific Queries

여러가지 타입과 특별한 거동.

null

널은 자신과 매치. 존재하지 않는 것도 매치. 어느 키가 널인지 확인하려면 그 키가 존재하는지도 확인해야함.
> db.c.find({“z” : {“$in” : [null], “$exists” : true}})

Regular Expressions

> db.users.find({“name” : /joe/i })  >> case insensitive matching.
몽고디비 Perl Compatible Regular Expression (PCRE)  사용.
정규식은 자신과 매치.. 정규식을 넣으면 그대로 인식.

Querying Arrays

$all

하나 이상의 요소와 매칭하는 어레이 검색 시. 순서는 무관.
> db.food.find({fruit : {$all : [“apple”, “banana”]}})
한 요소만 넣으면 그냥 검색한 것과 동일.
어레이를 검색하면 순서, 요소 수 등이 완전히 일치해야 검색이 나옴.
키.인덱스 로 찾을 수도 있음.
> db.food.find({“fruit.2” : “peach”}) >> 과일의 3번째 요소가 ‘배’ 를 찾음.

$size

> db.food.find({“fruit” : {“$size” : 3}})  >> 어레이 크기가 3인 요소.
크기의 영역을 주어 검색은 불가.. 대신 “size” or “number” 등을 같이 사용하는 것은 가능
> db.food.update({“$push” : { “fruit” : “apple”}, “$inc” : {“number” : 1}})  >> 이렇게 하고
> db.food.find({“size” : {“$gt” : 3 }})  >> 이렇게 영역 검색할 수 있음.

The $slice operator

> db.blog.posts.findOne(criteria, {“comments” : {“$slice” : 10 }})
음수는 마지막에서부터.
[23, 10] >> 23개는 스킵하고 24번째부터 34번째까지 10개 리턴.
따로 지정되지 않으면 모든 키의 값들 리턴.  다른 명령어와는 좀 다른 액션.

Querying on Embedded Documents

임베디드 다큐 쿼리의 두가지 방법 : 전체 다큐 / 각각의 키/밸류값.  >> 각각 쿼리하는 게 더 맞는 것 같네..
{ “Embeded” :  {“keyA” : “SomeValue”, “keyB” : “TheValue” }}  >> 이런 경우 다른게 끼어들거나 순서가 바뀌어도 쿼리 불능.
{“Embeded.keyA” : “Some”, “Embeded.keyB” : “blabla” }  >> 이렇게 하면 스키마가 바뀌어도 쿼리 가능.

이런 “도트” 노테이션으로 하위 문서에 접근 가능… 하지만, 도큐먼트 키에 “도트” 를 쓸 수 없다는 제약.

범위를 지정할 때… $elemMatch  –> group criteria.
> db.blog.find({“comments” : {“$elemMatch” : {“author” : “joe”, “score” : {“$gte” : 5 }}}})
임베디드 다큐 쿼리조건에서 다수의 키 사용 시… 에만 필요함.

4. $where Queries

검색이 애매한 경우 $where 절 사용하여 자바스크립트 구문을 실행하면 거의 모든 쿼리 가능. (함수형 언어 특성 ? )
어떤 두 키에 대한 값이 같은 것을 검색하는 경우.
> db.foo.find({“$where” : fundtion() {
for (var current in this) {
for (var other in this) {
if (current != other && this[current] == this[other]) { return true; }  } }
return false;
}});
스트링으로 처리 가능.
> db.foo.find({“$where” : “this.x + this.y == 10”})
느리므로 꼭 필요할 때만 사용.  각 다큐먼트는 BSON 에서 자바스크리트 객체로 컨버트 된 다음 ‘웨어’ 구문을 수행한다.
인덱스 사용 불가.
복잡한 쿼리를 하는 다른 방법은 ‘맵리듀스’..

5. Cursors

커서를 이용, find 로부터 결과를 받음.
쉐에서 커서를 만드려면, 다큐를 컬렉션에 넣고, 쿼리를 하고, 결과를 로컬변수에 할당.
> var cursor = db.collection.find();
> whild (cursor.hasNext()) { obj = cursor.next();  //  do stuff   ….  }
## cursor.hasNext() ::   cursor.next() .. fetch.
커서 클래스에서 foreach.. 루프 제공.
find 를 부르면 즉시 수행하지 않고 쿼리를 통해 질문할 때 수행함.
> var cursor = db.foo.find().sort({“x” : 1}).limit(1).skip(10);  # 이때는 수행 안함.
> cursor.hasNext()  # 이때 쿼리가 서버로 보내짐.  쉘은 처음 100개 혹은 4메가를 가져와서 디비 억세스가 잦지 않도록 함.
이 결과를 다 소진한 다음 쉘은 다음 결과를 가져옴.

Limits, Skips, and Sorts [57]

Avoiding Large Skips

Advanced Query Options

Getting Consistent Results

6. Cursor Internals

fk

MongoDB & Python Niall O’Higgins Ch 3, 4

Ch 3. Common MongoDB and Python Patterns

A Uniquely Document-Oriented Pattern : Embedding

RDBMS 의 join 과 같은 역할.
임베디드 다큐도 다큐와 똑같이 작업 가능.
한 키의 다수의 임베디드 다큐는 특히 유용. 즉, 값이 어레이인 속성. ;; 문법에 맞고 매우 유용한 구조.
일-다 관계 표현하는 자연스런 방식. 또는 부모-자식 관계.
한 유저의 ‘여러’ 이메일.. 일반디비에서는 2개의 테이블. 그리고, ‘조인’
몽고에서는 키와 상응하는 이메일들의 어레이..
[.] 기호를 통해 하위 값 가져오기 가능.  즉, dbh.users.find_one( { “emails.email” : “abc@kin.com” } ) .. 이런식.

이 외에도 $pull, $push .. 제공.. atomic append, removal of  sub – documents…
어떤 이메일이 더이상 유효하지 않을 때.. 다큐를 찾아서, 고쳐서, 업데이트 .. 해야하지만,  번거롭고 레이스를 불러올 수 있음.
섭-다큐의 3가지 주 작업 : 삭제, 삽입, 수정..

dbh.users.update ( { “username” : “thename” } ,
{ “$pull” : { “emails” : { “email” : “erse@the.com” } } } , safe=True)

이 소스는 다큐를 찾아내서 어레이에서 atomic fashion 으로 제거하여 레이스 원천봉쇄.
쿼리로 $pull 을 이용 가능.  예를 들어 어떤 조건이 맞는 모든 섭-다큐를 지울 때..
즉.. dbh.users.update ( {“username” : “thename”},
{ “$pull” : { “emails” : { “primary” : { “$ne” : True }}}, safe=True)

atoms 를 갖는 어레이에 적용 가능.  임베디드 다큐 ‘만’ 갖고는 작동 안함.

푸쉬는 어레이에 요소 atomically 추가할 때 사용. 끝에 추가하는 것만 가능.  <어레이의 처음에 추가하거나 임의의 장소에 넣는 업데이트 기능은 없음>
조건문이 없어서 간단함.

new_email = {“email”:”fooemail4@exmaple4.com”, “primary”:False}
dbh.users.update({“username”:”foouser”},
{“$push”:{“emails”:new_email}}, safe=True)
==> # 기존의 섭 다큐를 업데이트..  => positional operator [ $ ] 를 통해 가능.
예 :: {“$set”:{“emails.$.primary”:False}}, safe=True)
>>*<< 업서트 에서 사용 불가, first matched element 에서만 가능.

__ Page 29 __
<1> 임베딩 관련 작업 시, 다큐, 섭-다큐의 성능을 아는 것이 중요. 쿼리에 의해 다큐먼트가 불려오면 섭 다큐 등 모두가 메모리에 로딩됨.
즉, 임베디드 데이터를 가져오는 데 추가의 자원이 필요 없다.. (인코딩 cpu 같은 거 제외하고)
최상위 다큐먼트가 가용상태면 섭-다큐는 즉시 가용함.  이것을 ‘조인’에서는 여러 테이블을 읽으므로 성능이 떨어짐.
<2> 몽고에는 크기 제한이 있지만, 버전 따라 커지고 있음. 1.8 은 16메가.  시간에 따라 커지는 데이터가 아니고서는 충분함.
댓글을 다는 경우.. 한 다큐에 있을 때.
__ To embed , or not to embed. _ _ _ _ _ ^^
임베딩의 대안 >> 다큐를 분리된 컬렉션에 저장.  어플에서 조인하는 코드 구성.
보통 >>> 다 : 다  관계는 이렇게 조인..
보통 >>> 일 : 다  관계는 임베드.

Fast Lookups : Using Indexes in MongoDB [p31]

인덱스의 역할은 관계형디비와 크게 다르지 않음.  두가지 제공 : Btree indexes & geospatial indexes.
Btree 는 MySQL 등과 유사.  관계형 시스템에서는 빨리 찾기 위해 인덱스 이용, 몽고에서는 의미상 인덱스를 컬렉션의 특정 속성에 사용.
몽고는 여러 필드로 인덱스 확장 가능. (a.k.a. compound indexes)  한개 이상의 속성에 기반하여 쿼링하는 것을 미리 알고 있을 경우에 유용.
예 > 성, 이름으로 쿼링할 때.
몽고에서 비트리 인덱스는 “방향”을 가질 수 있음.  컴파운드 인덱스에서만 유용. 성능을 위해 쿼리와 소팅의 방향이 매칭되야 함.
비트리 인덱스는 데이터에 앞서 인덱스를 업데이트해야 하므로 쓰기 퍼포먼스에 타격. 인덱스를 조심히 선택해야 함.
Superfluous indexes를 피할 것.
인덱스는 스토리지도 차지함.   메모리 역시.   전형적인 <시간 대 공간 트레이드 오프> 시나리오임..
비트리는 컬렉션에 특별한 제한을 가할 때도 사용.
비트리는 값이 어레이인 경우도 지원. 어레이의 각 아이템은 인덱스에 적당히 저장되서 다큐의 빠른 조사가 가능. 태깅 기능에 유용.
비트리는 임베디드 다큐도 지원.   예> 이메일을 섭 다큐로 지정하고 인덱스로 사용할 때.
서버 쪽 소팅 퍼포먼스에도 중요. 4메가 이상의 결과에 대해 소팅하려고 할 대 소트 키에 인덱스를 지정해야 함.  개발시에는 예상치 못한 거대한 실제 데이터에 대해 쿼리할 때 예외를 발견하는 것을 간과하기 쉽다.

파이 몽고 드라이버로 인덱스 생성.
Collection.create_index()  # method  single-key OR compound (튜플) indexes 생성.
dbh.users.create_index([(“first_name”, pymongo.ASCENDING), (“last_name”, pymongo.ASCENDING)]) # 리스트로 인덱스 생성 예.
인덱스에는 자동 이름이 붙지만 커스텀 네이밍 가능
dbh.users.create_index([(“first_name”, pymongo.ASCENDING), (“last_name”, pymongo.ASCENDING)], name = “myIndex_name”) # 커스텀 이름.

인덱스를 만들면 기본으로 디비를 ‘잠군다’. 큰 컬렉션에서 시간이 걸리므로. 백그라운드에서 생성 가능. 당연히 시간은 좀 더 걸리지만 디비가 ‘가용’ 상태.
dbh.user.create_index(“username”, background-True)

Unique constraint..  unique=True
유니크 옵션은 몽고에서는 관계디비와는 다름.  첫번째를 제외하고 중복 요소 제거.. dropDups = True

인덱스 제거는 쉽다. drop_index() method.

Collection.index_information() # Python .. 인덱스 조사.   Dictionary 리턴.  인덱스 이름 = 키, 밸류 = 또다른 딕셔너리.
이 딕셔너리는 key ..로 불리는 ‘키’ 를 포함. 인덱스 방향 포함한 원래 인덱스 specifier.   create_index에 넘겨진 것.   옵션들도 포함.

Location-based Apps with MongoDB : GeoSpatial Indexing [p33]

Points of interest (POI)

몽고는 Gustavo Niemeyer 가 개발한 geohasing 알고리즘 사용.
현재로서는 포인트-베이스 쿼링만 가능.
$near $within $box $circle $polygon (MongoDB v 1.9)
GPS 좌표만 가능 (-180 ~ 180 )
파이썬 딕셔너리는 순서가 없으므로 bson.SON 을 이용할 것.

인덱스는 하나의 위치인덱스만 포함 가능.. 다른 것과 같이 컴파운드 인덱싱 가능.

$near :: 기본으로 100개 결과 리턴. 최대값 지정 (5도 정도가 적당) 1도 = 69마일.
$nearSphere $centerSphere :: radian.

Code Defensively to Avoid KeyErrors and Other Bugs [p37]

Update-or-Insert: Upserts in MongoDB

save() : _id 없이 실행하면 새로운 다큐 삽입, _id 가 있으면 업데이트.  ;; 업서트 ..

업데이트는 두가지 경우를 각각 수행함. 문서가 있으면 업데이트 하고, 없으면 새로 만든 후에 업데이트를 실행함.

Atomic Read-Write-Modify : MongoDB’s findAndModify [p40]

업데이트 결과를 가져올 때.. 레이스 컨디션 회피 명령어.

Fast Accounting pattern

점수, 랭킹 계산의 경우.. 데이터 크고, 빠르게 계산 필요.

 

 

Ch 4. MongoDB with Web Frameworks

Pylons 1.x and MongoDB

WSGI-based web frameworks. 2005 09.  v1.0 at 2010
“one-size-fits-all”  < — > Pylon
So modular.. easy to add MongoDB

Pyramid and MongoDB

Pylons 2.0 ..
scaffold ..

Django and MongoDB

Mango..
10gen .. sample app.

2013. 2. 23.

 

몽고 디비 MongoDB The Definitive Guide.. Ch. 3

Ch. 3  Creating, Updating, and Deleting Documents

Add, Remove, Update, level of safety vs. speed

Inserting and Saving Documents

Batch Insert

Single TCP request.  한꺼번에 보내면 헤더 중복이 안됨. 배치..
배치는 어플에서 사용하도록 의도. 많은 센서 데이터. 단, 하나의 컬렉션에 여러 다큐를 넣을 때에만 가능.
로 데이터 처리는 mongoimport 를 사용.
16 MB 한계.

Inserts : Internals and Implications

Insert :: BSON 으로 변환. 디비는 이 형식을 이해하고 _아이디 체크. 4 MB 를 넘지 않으면 데이터 validation 을 수행 안하고 바로 그대로 저장.
부작용 : 불량한 데이터 삽입 가능. injection attack 에 안전 ??
모든 메이저 언어의 드라이버는 유효성 검사를 수행.
확실하지 않은 드라이버를 돌릴 때는 디비 서버를 –objcheck 옵션으로 시작할 수 있음.

4메가 이상은 저장 불능. 임의의 한계. 불량 스키마 예방, 퍼포먼스를 위한 것임. 사이즈를 보려면 Object.bsonsize(doc) 을 쉘에서 입력.
전쟁과 평화가 3.14 메가임.

디비는 삽입 시 별로 하는 일이 없으므로 인젝션 어택에 약하지 않음.  고전적인 인젝션 어택은 몽고디비에서는 불가능. 대안 적인 어택.

Removing Documents

db.users.remove()  >> user 컬렉션 전체 삭제. 컬렉션은 살림. 인덱스 삭제. 쿼리를 통해 조건 부여 삭제.

db.mailing.list.remove( { “opt” : true } )  # mailing.list 컬렉션의 opt 값이 참 인 ㅅ람 모두 삭제.

삭제는 undo 없음.

Remove Speed

1만개 삭제 : 맥북에어에서 46초..  드랍을 하면 0.01 초..
전체 컬렉션과 인덱스 삭제..

Updating Documents

2 parameters : query document, modifier document

Document Replacement

Atomic.  Last update will “win” ..  “survive ” ..
같은 조건의 데이터가 여러개 일 때 주의..   update 가 분명한 다큐를 가리켜야함.  “_id” 처럼..

Using Modifiers

데이터 일부만 변경 시..  altering, adding, removing keys, manipulating arrays, embedded documents, _id 는 변경불가.

db.analytics.update({“url” : “www.example.com”},
… {“$inc” : {“pageviews” : 1}})   # 페이지 뷰 늘리기.

[1] Getting started with the “$set” modifier

키에 상응하는 밸류 세팅. 키가 없으면 생성.  밸류의 타입도 변경 (스트링 -> 어레이)
임베디드 다큐의 속성 변경 가능. { “$set” : { “author.name” : “some name” } }  …
$unset :: remove the key.

[2] Incrementing

$inc modifier. :: 현재의 키 증가시킴, 없으면 키 생성. 변경 가능 숫자일 때 유용.  analytics, votes ..  게임 점수 증가.  int, long, double 에 가능.

[3] Array modifiers

$push : 추가..  동일한 내용을 추가하지 않으려면 $ne 쿼리를 병행행
$addToSet : 역시 동일한 내용은 추가 안함.  $each 와 함께 여러개 삽입 가능. ($ne / $push 사용 불가)
<어레이 요소 삭제 방법>
[1] $pop :: 큐 / 스택 처럼 사용하고 싶으면 $pop 사용. { $pop : { key : 1 } } 는 어레이의 끝 요소 삭제. { key : -1} 은 처음 멤버 삭제.
[2] $pull ::  조건으로 검색. 삭제.  매칭되는 여러개 모두 삭제.

[4] Positional array modifier

어레이의 여러 값 변경 방법.  포지션 또는 포지션 연산자 $ 사용.
{ “$inc” : { “comments.0.votes” : 1 } }   # 포지션 지정.. 0번째.  하지만, 많은 경우 위치를 모름. 이때 $ 사용.

db.blog.update( {“comments.author” : “John” },
… { “$set” : { “comments.$.author” : “Jim” } })  # 여러 커멘트에서 작성자 이름을 변경.  (첫번째 것만)
## 첫번째 매치 만 업데이트 함…

[5] Modifier speed

각 명령어마다 성능차이 존재. $inc 는 키에 해당하는 값만 변경하므로 매우 빠름. 대신 어레이 변경자는 다큐의 크기를 변경하므로 느려짐.
($set 역시 비슷함.)
몽고는 사이즈 변경에 따른 완충장치를 두었지만, 원래보다 훨씬 크게 고치면 새로 지정함. 어레이 크기 조정, 어레이 수정 등은 속도 저하.
예제 파이썬 프로그램.   10배 차이..
$push 가 버틀넥인 경우 임베디드 어레이를 별도의 컬렉션에 두는 것도 한 방법.

Upserts [p36]

문서를 찾아서 업데이트하거나, 없으면 생성. 쿼리와 인서트 를 하는 일반적인 경우는 ‘레이스’ 조건 직면.

The ‘save’ Shell Helper

업서트와 비슷. 다큐 인자를 하나 받음. _id 키가 있으면 업서트 실행, 없으면 인서트 실행.
쉘에서 신속하게 수정할 수 있는 방법.

Updateing Multiple Documents [p38]

Update 는 첫번째 요소만 수정. 4번째 인자에 true 를 세팅함으로 모든 멤버 수정 가능. (나중에 바뀔 소지가 있음..  그러므로, 항상 값을 넣을 것. 참/거짓)
멀티 업데이트는 스키마 변경시에 당연히 유리.  생일 선물 주기 기능 ..
몇개가 수정되었나 ? getLastError database command.  ==>  “n” : 5

Returning Updated  Documents [p39]

< getLastError > 로 부터는 제한된 정보밖에 없다. 그래서 findAndModify 가 필요.
일반적인 업데이트와는 약간 다르게 불리고, 느림. 디비 응답을 기다려야 하기 때문.
큐를 조작하고 겟-셑 등의 미세 조작을 수행할 때 편하다.

예> READY, RUNNING DONE 의 세 상태를 갖고 있으면.
“레디”를 가져와서
이놈을 “러닝” 으로 바꾸고.. 액션을 시작한 후 끝나면
“던” 으로 바꾸는 과정을 해야 함.
이 과정은 “레이스 조건”. 대안은 복잡.
타이밍에 있어서도, 한 프로세스는 계속 놀고 있을 수 있음.  이럴 때 적합..
< findAndModify > 는 아이템을 리턴하고 업데이트를 한 조작내에서 가능.
리턴된 놈은 업데이트 전이지만, 컬렉션에서 찾아보면 업데이트가 되어있슴.
<삭제 : “remove” : true … >도 가능..

Key of findAndModify
findAndModify
query
sort
update
remove
new

매칭 다큐가 없으면 에러.
한 개의 다큐만 가능.
<업서트> 로 사용 불가.  기존의 다큐만 수정 가능.
속도 : find, update, getLastError 를 연속 실행할 때 만큼 느림.

The Fastest Write This Side of Mississippi [p41]

삽입, 제거, 업데이트는 보내고 잊어버리는 타입. 빠르다. fire-and-forgot
로그 기록 등에서는 무방하나 결재 시스템에서는 허용할 수 없음.

Safe Operations

관계형 디비 위의 어플리케이션중 많은 부분이 리턴 코드를 확인 안함. 몽고는 디폴트로 체크하지 않음.
Safe version 은 getLastError 명령어를 실행함. 드라이버는 디비 반응을 기다리고 적당한 에러를 핸들하고 예외를 던짐.
성공하면 그에 따르는 정보를 포함함.

Catching “Normal” Errors

Safe operation 은 ‘이상한’ 디비 행동을 디버그 하는 방법이기도 함.  개발중에는 널리 사용해야 함. 여러 에러를 방지할 수 있음.  가장 흔하게는 중복 키 에러.
중복키의 경우 삽입 실패를 모르고 넘어갈 수 있음.

Requests and Connections

몽고디비 서버의 각 연결마다 디비는 연결의 요청에 따른 큐를 생성한다. 클라이언트가 연결에 요청하면 큐의 끝에 놓여지고, 다음의 요청은 큐에 있는 작업이 실행된 후에 실행된다. 그러므로, 단일 커넥션은 디비의 consistent view 를 갖고 자신의 쓰기를 읽을 수 있다.
이것은 per-connection queue. 쉘을 두개 열면 이것은 2개의 연결임. 한쪽에서 넣은 후에 다른쪽에서 읽으면 리턴 못받음. 하지만, 한 쉘에서는 삽입 후 쿼리는 리턴 함.  수작업으로는 재현 힘들지만 바쁜 서버에서는 가능한 얘기.
한 쓰레드에서 작업하고 다른 쓰레드에서 확인하는 것은 무의미.   특히, 루비, 파이썬, 자바 드라이버에서.   => connection pooling 사용.

몽고 디비 MongoDB The Definitive Guide.. Ch. 1, 2

그동안 시간이 많았는데 블로깅 하는 걸 잊고 살았슴다. 서버 개발자 찾아 삼만리..  하다가 조금씩 공부해 보기로 작정.. 일단 언어는 파이썬.. 디비는 당근 MySQL 로 생각했었는데, 이것도 요즘 대세인 하둡, NoSQL 쪽으로 가기로.. ㅎㅎ 점점 게임과는 거리가 멀어지는 듯.. 그러다가 몽고, 카산드라 사이에서 잠깐 고민하다가… 몽고 디비에 관한 책을 와우에서 구해서.. 둘다 얇고.. 하나는 파이썬과도 통하고… 해서 당장 오늘 시작

1장. Introduction

Powerful, flexible, scalable data store.. ? 데이터 [베이스] 가 아니라 [스토어] 라고라고라?.. 맵리듀스 스타일의 압축 도 지원하고.. 다양한 특성을 갖고 있다.

A Rich data model

‘row’ 단위보다는 ‘document’ 단위로 저장하여 스키마를 변경해도 유연하게 처리 가능하다.. RDB 는 꽉 짜여진 것이고… 몽고는 좀 느슨하다는 것 같음. 하나의 레코드로 복잡한 구조를 표현 가능하다. 또한 ‘스키마-프리’. 변경할 스키마가 없으므로 대량 데이터 이동 등이 불필요. 새로운 / 사라진 키는 모든 디비를 똑같이 강제하기 보다는 어플리케이션 레벨에서 처리.  데이터 모델 진화에 유연하게 대처 가능.

Easy Scaling

데이터가 커지는데 대처하는 방법 : Scale Up (bigger machine), or  Scale Out (partitioning data across more machines) 몽고는 처음부터 스케일 아웃에 대비해 설계됨. Document-oriented data model 은 자동으로 여러 서버에 나눠 저장. 개발자는 로직에 집중할 수 있음. 저장공간이 더 필요할 때 단지 클러스터에 기계를 더 붙이고 나머지는 디비가 알아서 함.

Tons of features

Indexing :: generic secondary indexes.  geospatial indexing.. Stored JavaScript :: Instead of stored procedures, JS functions… Aggregation :: Map reduce. Fixed size collection :: capped collections .. such as logs.. File storage :: large files and meta data.

.. Without Sacrificing Speed

속도를 위한 … binary wire protocol   memory mapped files ..dynamic query optimizer

Simple Administration

설정이 적다.. ㅎㅎㅎ

2장. Getting Started.

> Document : 기본 데이터 단위.. row 에 해당.
> Collection : 테이블 ..
> 하나의 인스턴스가 여러 디비를 호스트 할 수 있음.
> 강력한 JavaScript Shell.
> _id : special key.

Documents

>   ordered set of keys with associated values  > 언어마다 다른 정의 ? 자바스크립트에서는 object

{“greeting” : “Hello, world!”, “foo” : 3 }
>> 순서가 있음.
>> 밸류는 특정 테이터 타입이 있음.
>> 키는 스트링.  은 제외.  키의 종료를 의미.   $와 . 역시 예약어.  _ 로 시작하는 것도 피할 것.
>> 타입, 케이스 센시티브 함..
>> 중복 키 금지.

Collection

Group of Documents.

Schema Free

컬렉션은 스키마-프리.
아무거나 들어갈 수 있는데, 왜 별도의 컬렉션이 필요한가?
> 종류별로 구별
> 타입을 리스트 하기보다, 컬렉션을 리스트하는게 더 빠름.
> 인덱스 ??

Naming

> “”, /0, system 으로 시작, $ 불가

Subcollection

[.] 으로 분리 (예: blog.posts) 이때 blog 와는 전혀 무관. 이름만 지음.
드라이버에서 유용한 방법 제공.
데이터를 구성하는 유기적 방법을 제공하므로 ‘강력 추천’

Databases

컬렉션으로 그루핑하고, 컬렉션들을 데이터베이스로 그루핑한다.  하나의 인스턴스는 여러 데이터베이스를 호스트 가능.  완전히 독립적으로.
데베는 독립된 퍼미션, 독립된 파일에 저장.
하나의 어플은 같은 데베에 저장을 추천. 여러 파일은 여러 어플이나 동일 몽고디비 서버의 여러 사용자일 때 .
데베는 이름으로 구별.

> “” 널문자 불가
> 소문자
> 64바이트

특별한 디비 네임.

> admin : root database.
> local :
> config :

mds 디비의 blog.posts 컬렉션이면 mds.blog.posts 네임스페이스를 얻게 됨.  네임스페이스는 121바이트 한계.

Getting and Starting MongoDB

서버로 실행됨.  => mongod  실행.
인자 없이 실행시키면 디폴트 데이터 폴더 이용. /data/db/  & port 27017. 없거나 쓰기불능이면 페일. 포트 페일도 페일. => 다른 인스턴스가 돌고 있을 때.
기본 http 서버 셋업. 28017.  관리를 http://localhost:28017 웹 브라우저로 가능.
종료 : Ctrl – C

MongoDB Shell

JS shell. 관리에 매우 편함.

Running the Shell

JavaScript interpreter 전체임.  멀티라인 가능. 문장이 끝났는지 검토.

MongoDB Client

또한  stand-alone MongoDB client 이다.  기동 시 셀은 몽고 디비의 test 디비에 연결하고 이것을 전역변수 db 에 할당함.  이 변수가 주된 접속 포인트임.
애드온. SQL shell과 유사함. 추가 함수는 없지만 나이스한 구문 제공.

> use foobar
switched to db foobar

자바 스크립트이므로 변수를 치면 변수를 스트링으로 바꿔 프린트한다.
컬렉션 역시 db 를 통해 접속 가능. db.baz 는 baz  컬렉션 리턴.

Basic Operations with the Shell

CRUD (create / read / update / delete)

Create

함수 insert 는 컬렉션에 다큐먼트 추가.

> post = { “title” : “My Blog Post” , “content” : “Here’s my post.”, “date” : new Date() }
> db.blog.insert(post)  .. 저장됨.
> db.blog.find()  확인.  “_id” : ObjectID (“asd2dbad33kj;adsfklj3kl;sd”)  이런게 추가됨.

Read

find() , findOne()  20개 다큐먼트 보여줌.

Update

두개의 인자. 어느 다큐먼트를 업데이트 할지 criteria, new document.

> post.comments = []
> db.blog.update( { title : “My Blog Post” } , post)  >> “comments” key 가 추가됨.

Delete

인수 없이 불려 모든 걸 지움.

> db.blog.remove( { title : “My Blog Post” } )  >> 요것만 지움.

Tips for Using the Shell

> help  >> built in help..
> db.help();  or   db.foo.help();

괄호 없이 함수명을 치면 뭘하는 지 알 수 있다.

> db.foo.update

Inconvenient collection names

디비 클래스의 속성만 아니면 컬렉션을 가져올 수 있다. db.version 은 디비 함수이므로 안된다. ??   getCollection 사용.
> db.getCollection(“version”);
예를 들어 foo-bar 는 유효한 컬렉션 이름이지만, 자바스크립트에서 variable subtraction 이다.
> db.getCollection(“foo-bar”)

JavaScript x.y = x[‘y’] 임.

Data Types

Basic Data Types

JSON 식. 자바스크립트와 비슷.   JSON : null, bool, numeric, string, array, object 6가지 종류.. 제한적임.  언어에 따라 다르지만 몇가지 추가함.

Numbers

몽고 디비는 4 / 8 비트 정수, 8비트 실수가 있으므로 자바스크립트를 약간 우회?해야 함.
디폴트 : 몽고에서는 모든 숫자는 더블 로 간주.   디비에서 4정수를 꺼내 가공한 후 저장하면 더블로 저장됨.
또다른 문제는 8정수가 더블로 표현되지 않음.   “floatApprox” 와  “top” “bottom” 키워드로 표현..

Dates

항상 new Date() 하라.. 객체 리턴.. 그냥 하면 스트링만 리턴.   자바스크립트 방식..  디비에는 기준 시점 이후의 밀리세컨드로 저장.

Arrays

어레이 내에 다른 타입을 가질 수 있음.  어레이를 멤버로 가질 수도 있음.
몽고는 이 구조를 이해함.  어레이에 대한 쿼리 가능..
원자적 업데이트 가능.. (하나를 바꾸는 액션)

Embedded Documents

Value 값으로 할당된 다큐먼트..   주소 : { 나라 : 콩고, 시 : 시티, 구 : 용산 } 이런식으로 표현 가능.. RDB 에서는 다른 테이블 필요하지만 몽고는 불필요
더 자연스럽게 정보를 표현.
단점 >> 정보가 반복될 수 있다.

_id and ObjectIds

어느 타입이든 가능.  각 컬렉션에는 고유한 아이디 필요.. 다른 컬렉션은 동일 아이디 가능.

ObjectIds

12 bytes. 24 hexadecimal digits.
> 4 byte : Time Stamp .. 입력 순서대로 정렬 가능..  암시적 타임 스탬프.
> 3 byte : Machine .. hash of the machine’s hostname.
> 2 byte : Process ID
> 3 byte : Incremental.  256 ^ 3 = 16,777,216 … in a single second..

Autogeneration of _id