• 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&noti-> "Slave" : oplog read&redo
        • Master:읽기/쓰기 , Slave:읽기
        • "쓰기 및 읽기" 일관성 을 <-> '성능' 과 trade-off 하는, 옵션&튜닝 가능.
      • 3개 이상의 인스턴스로 Replica-Set 을 구성하고, Primary/Secondary 자동선출.
      • Auto Fail-Over 지원.
      • 트랜잭션은 원자적 처리 정도만 지원함. (application단에서 커버 해야하는 ㅠ 단점)
    • 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
  • 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 하나 리턴.
    • 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}}})
  • ...
  • // 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가 생각보다 엄청 유용한거 같다.

-끝-

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

+ Recent posts