- 0) Document란?
- JSON, XML,YAML 같이... 구조화된 데이터.
- RDBMS의 Row와 비슷.
- 예) _id, username, name 은 key이고, 그 오른쪽이 value.
- {"_id": ObjectId("5099803df3f4948bd2f98391"),
- "username": "velopert",
- "name": { first: "M.J.", last: "Kim" }}
- _id 는 primary-key 와 비슷.
- 0) Collection란?
- 유사한 용도의 Document들에 그룹.
- RDBMS의 Table과 비슷.
- 하나의 Collection에 서로다른 Schema... 즉, Dynamic-Schema의 Document들로 구성.
- 0) Field란?
- Document 내에 Key:Value으로 구성이 됨.
- RDBMS의 Column과 비슷.
- 당연, Column의 Schema랄것이 없는 Schemaless으로~ 유동성 제공.
- Key에 대한 Value로 다양한 타입이 지원되며, Embedded-Document도 지원된다.
- (즉, RDBMS처럼~ 더이상 JOIN 따위를 하지않고... 휴몬구스하게 데이터를 구조화 하는 컨셉!)
- (RDBMS의 join을 embedding 및 linking 으로 대체)
- 0) Map/Reduce,Aggregate
- https://github.com/stepanowon/nosql_script/blob/master/mapreduce_vs_aggregate.MD
- https://github.com/stepanowon/nosql_script/blob/master/mapreduce.pdf
- // TODO : ...
- RDBMS의 group by 와 비슷.
- Map/Reduce 및 Aggregate 내장으로, 강력한 집계기능을 제공함.
- Map/Reduce : Map((K,V)쌍으로 만듬) -> Shuffle(정렬함) -> Reduce(집계)
- Aggregate : Pipeline을 구성하여, 순차적으로 처리. [Pipeline] -Output-> | -Input-> [Pipeline]
- 1) MongoDB 란?
- huMONGOusDB : 기존 RDBMS의 2차원적 데이터는... 우리에게 자연스럽지 않다!
- 즉, 더이상 정규화에 노력말고~ 복잡한 내용을 한곳에 단순히 합쳐버린 집합(Aggregation)적 비정규 데이터.
- 효율성을 위해서, BSON 형식으로 저장하고~ 비정규 데이터를 처리하는 연산비용이 높지않기에 가능한것.
- 손쉬운 자동샤딩, Replica-Set, Index(Geospatial, Hashed, Unique, Spars, Text) 등 강력한 지원.
- 활용예)
- 'Embedded Document 및 Array' 필드에 인덱싱 기반 응용기능!!!
- GPS 지구체 위경도 인덱싱이 엄청! 좋다고 추천함. (예:반경 몇 Km안은 검색하라!)
- Full Text Search Index 지원하는데... 한국어 형태소 없고, ElasticSearch에 비해 성능 100배 낮다고 비추.
- TTL Collection
- GridFS ???
- 부적합예)
- 복잡한 다중 트랜잭션이 요구되는 상황. (원자적 수준만 제공)
- 엄격한 일관성 및 무결성이 요구되는 상황. (Join 지원X,비정규데이터중복)
- Insert 및 Update가 빈번한 상황. (Document 크기증가 -> 단편화 Fragmentation 발생 -> 성능저하)
- 2) MongoDB 구조
- Server > Database > Collection > Document > Field{key:value}
- 2) MongoDB 복제 와 자동샤딩
- Replication :
- 전형적인 Master/Slave 구조. (Slave가 Master를 바라보면서... 계속 복사)
- "App" -write-> "Master" -oplog¬i-> "Slave" : oplog read&redo
- Master:읽기/쓰기 , Slave:읽기
- "쓰기 및 읽기" 일관성 을 <-> '성능' 과 trade-off 하는, 옵션&튜닝 가능.
- 3개 이상의 인스턴스로 Replica-Set 을 구성하고, Primary/Secondary 자동선출.
- Auto Fail-Over 지원.
- 트랜잭션은 원자적 처리 정도만 지원함. (application단에서 커버 해야하는 ㅠ 단점)
- 전형적인 Master/Slave 구조. (Slave가 Master를 바라보면서... 계속 복사)
- Auto-Sharding :
- 샤드단위로, 데이터를 균등하게 자동으로 분산 할 수 있어야 함.
- 선택적으로 가능.
- 즉, 단일 샤드로 운영하다 -> 샤드 클러스터로 확장하기 가능.
- 특정 Collection만 샤딩 하도록 하는것도 가능.
- 즉, 좀더 효율적으로~ 점점 쌓이는 특성의 Collection만 샤딩하는게 가능.
- 보통 1개의 샤드는 -> 3개의 인스턴스 Replica-Set으로 구성. (즉, 3샤드 == 9개 인스턴스 필요)
- '샤드-키'는 잘 분포가 될 수 있는 값으로 해야! 성능이 보장됨.
- mdb라우터가 '샤드-파티션'을 각각 찾아 처리해서... 해당 "Index Field"으로 쿼리하는게 좋다.
- 즉, "Index Field"는 복합적인 Sequence+Random 식으로 잘 정해야 한다.
- 카디넬리티(Cardinality)
- 어느정도 잘 분포되어 있는 그 정도를 나타내는 용어.
- 전체 Document 갯수를 10등분 이상 정도로 할 수 있는게 좋음.
- Sequential Vs Random
- Sequential : 초창기에 HotSpat 발생할 가능성 높아서, write성능 저하. 연속데이터 read는 좋음.
- Random : write성능 좋음. 연속데이터 read는 안좋음.
- mdb라우터(mongos)
- `Auto-Balancing` 및 'Auto-Chunk분할' 등의 Auto-Sharding을 하는 핵심.
- 각 '샤드-키' 구간을 chunk라는 단위로 관리함. (디폴트 사이즈 64MB)
- 각 chunk의 사이즈가 오버되면, 자동으로 분할 및 리밸런싱 하는것!
- ConfigDB
- 샤드정보 및 메타정보를 관리하는 별도의 서버.
- 즉, mongos가 ConfigDB를 기반으로 자동으로 변하는 샤드정보를 저장 및 처리.
- 샤드 클러스터 구조
- 샤드 자체엔 Fail-Over 기능이 없으니, 각 샤드를 Replica-Set으로 구성함.
- ConfigDB도 매우 중요하니, Replica-Set으로 구성함.
- 예)
- 서버1 : Primary1 - Secondary3 - Arbiter2 - Config1
- 서버2 : Primary2 - Secondary1 - Arbiter3 - Config2
- 서버3 : Primary3 - Secondary2 - Arbiter1 - Config3
- 샤드단위로, 데이터를 균등하게 자동으로 분산 할 수 있어야 함.
- Replication :
- 3) MongoDB 모델링
- 함께 사용할 정보는 하나의 Document에, 그렇지 않으면 서로다른 Document로 저장.
- (Read시, join을 하는게아니라 Write시, join을 하는것...)
- 예) [게시글], [뎃글], [tag정보]
- { "_id": ObjectId("..."),
- "title": "제목", "content": "내용", "username": "작성자", "likes": 159,
- "comments": [ {"username":"익명1","msg":"하하하하"},{"username":"익명2","msg":"호호호호"}],
- "tags": [ "#음악", "#발라드", "#최신" ] }
- 4) MongoDb 개발
- db.collection.insert(document)
- 해당 Document를 삽입.
- _id 값은 명시적으로 입력하지 않으면, 자동으로 유니크하게(timestamp+Hash+PID+Increment) 생성됨.
- db.collection.find(condition, projection)
- db.collection.findOne(condition, projection)
- condition= 특정 조건의 Key:Value인 Document를 조회.
- 예) .find({"username":"홍길동"}) .find({"counts":{$lte:30}}) .find({"tags":{$in:["#음악","#힙합"]}})
- $lt, $lte, $gt, $gte, $in, $or 등등 제한자 제공. (equl 및 and 가 디폴트)
- {"필드":null} 조회시, 해당 필드가 없는것도 포함이 되어서... $exists 라는게 제공.
- LIKE 절은 없고, `정규식`을 사용해야함.
- 다양한 쿼리연산자도 제공됨. ($regex연산자, $where연산자, $elemMatch연산자, ... )
- Array Field 에 인덱스를 걸수있다는것이! 참 강력해 보임...
- {"어레이":"apple"} == 해당 Array에 "apple" 포함 여부.
- {"어레이.1":"banana"} == 해당 Array[1] 두번째값이 "banana" 인지 여부.
- {"어레이":[apple,banana,corn]} == 해당 Array가 정확히 순서까지 일치 여부.
- {"어레이":{$all:[appel,banana]}} == 해당 Array가 "apple" 및 "banana" 모두 포함하는 여부.
- projection = 조회된 Document에서 특정 key-value만 보여짐.
- find()는 Cursor객체 리턴. findOne()는 Document 하나 리턴.
- condition= 특정 조건의 Key:Value인 Document를 조회.
- Cursor객체 메서드
- .sort() = 복합적 정렬기준. (오름차순 or 내림차순)
- .limit() = 조회결과 갯수제한.
- .skip() = 조회결과 스킵수 (페이징 처리) // 많은 데이터를 다 가져온뒤, 버리는 구조라~ 안티패턴 되기쉽다...
- .count() = 카운트.
- .hasNext() .next() =
- db.collection.update(condition, document, 옵션)
- 기본적으로 하나의 Document를 원자적으로 업데이트 제공.
- Document 자체가 치환되는 방식.
- 특정 Field만 수정 하려면, 적절한 $제한자를 적용해야 함. ($set, $inc, $addToSet, $push, $pop, $pull)
- $제한자 없이, 특정 Field를 수정하면... 기존 Field 다 날라감.
- 즉, Document를 치환으로 쉽게 바꿀수있어야~ Schemaless가 가능해지는것!
- 옵션
- upsert = 디폴트 false. (true : 해당 condition의 Document가 없으면 삽입)
- multi = 디폴트 false. (true시 : 해당 condition의 Document를 모두 업데이트)
- writeConcern = wtimeout 등 Document 업데이트 할 때 필요한 옵션.
- 예)
- .update({name:"Abet"}, {$set:{age:20}})
- .update({name:"Che"}, {$push:{tags:{$each:["영화","액션"],$sort:1}}})
- db.collection.insert(document)
- ...
- // TODO : ...
- ...
- 5) mongoDB인덱스
- Index가 없으면, Collection의 Document를 하나하나씩 스캔해야함...
- 기본인덱스 _id = MongoDB에서 unique(유일)함.
- Single(단일)필드 인덱스 = 하나의 key를 사용자가 지정.
- Compound(복합)필드 인덱스 = 복수의 key를 사용자가 지정.
- Embedded Document인덱스 = Document 안의 Document에 적용할때 사용.
- Array Field 인덱스 = Array의 Field에 적용할때 사용.
- 속성
- Unique 속성 = PK같은거~
- Partial 속성 = 특정 Document들에만 적용
- TTL 속성 = Date필드에 적용해서 특정시간만료시, 해당 Collection에서 Document를 제거.
- sparse, unique, geospatial, text, hashed,
- 6) mongoDB 자바 프로그래밍
- Document 객체를 일일이 사용하기는 힘들다
- ObjectMapper가 필요하다. (BSON <-> 객체) (추천 : Spring Mongo, Jongo)
- 7) mongoDB 설치
- Replica-Set 구성 : http://minsql.com/others/mongodb-replica-set-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0
- 클라이언트 툴 : 3T Studio, mongobooster(NoSQLBooster), Compass
- 8) 핵심정리
- Array , Embedded Document -> 1:N , N:M
- Index (B+ Tree)
- Sort -> Aggregate
- Sharding -> Shard Key (카디넬리티 확포되지 않아, 적은 샤드로 아주많이 고르게 하면... chunk분할 이슈터짐)
- 9) 모델링
- 1:N
- Embedded : 부모객체 내에서만 자식객체가 사용될때. (예: 주문정보와 주문상세정보)
- Linked : 부모객체와 자식객체가 별개로 사용될때 (예: 상품분류정보 상품정보) ($db, $ref, $id 으로... Application단 객체단위 매핑(fetch()) 너무 잘 되있음.)
- N:M
- Array Field 를 이용해서~ 다대다 단방향or양방향 참조 하도록 하면 됨.
- Tree
- Embedded Tree, Linked Document, ...
- Dynamic Field
- 객체 상속 다형성 같은 느낌... sparse가 생각보다 엄청 유용한거 같다.
- 1:N
-끝-
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup
https://www.zerocho.com/category/MongoDB/post/579e2821c097d015000404dc
https://docs.mongodb.com/manual/reference/operator/aggregation/toObjectId
https://docs.mongodb.com/manual/reference/operator/aggregation/unwind
'NoSQL' 카테고리의 다른 글
HBase (0) | 2019.05.18 |
---|---|
Cassandra (0) | 2019.05.18 |
redis (0) | 2019.05.18 |
MariaDB (SQL) (0) | 2019.04.24 |
PostgreSQL (작성예정) (0) | 2019.04.10 |