Modeling
Facebook mongoDB Korea 김동한
MongoDB
• Document Oriented Storage
• JSON 스타일의 Document
• 간결하고 강력한 동적 스키마 구성
• Full Index Support
• 어느 속성에나 인덱스 설정 가능
• Replication & HighAvailability
• LAN과 WAN을 이용한 미러링과 빠른 성능
Introduction
ROW vs JSON
번호 가수명 본명 출생지 소속 연관_01 연관_02
1 태양 동영배 서울 YG 빅뱅 G드래곤
var json = {
가수명 : "태양",
본명 : "동영배",
출생지 : "서울",
소속 : "YG",
연관 : ["빅뱅","G드래곤"]
}
Introduction
mongoDB 구조
{JSON} COLLECTION
DATABASE
Introduction
Terminology
RDBMS mongoDB
Database Database
Table Collection
Index Index
Row Document
Column Field
Join Embedding & Linking
Primary Key Object _id
Introduction
$lookup
Modeling
Modeling Basic
3 Types Document Storage Model
RDBMS ERD
테이블_가수
PK 1001
이름 태양
본명 동영배
소속 YG
테이블_앨범
PK 2001
FK 1001
앨범명 RISE
발매일 2014.06.03
테이블_곡리스트
PK FK 트랙번호 곡명 작곡자 길이
3001 2001 1 Intro Peejay 01:30
3002 2001 2 눈, 코, 입 Teddy 04:12
3003 2001 3 새벽한시 Teddy 02:11
테이블_그룹
PK 4001
그룹명 빅뱅
소속 YG
Modeling Basic
The JSON is The Schema
{
"앨범명":"RISE",
"가수명":"태양",
"발매일":"2014.06.03",
"곡리스트":[ {"트랙번호":"1","곡명":"Intro (RISE)","작곡자":"Peejay","작사자":["타블로","Choice37","태양"],"길이":"01:30"},
{"트랙번호":"2","곡명":"눈코입","작곡자":"Teddy","작사자":"Teddy","길이":"04:12"},
{"트랙번호":"3","곡명":"새벽한시 (1AM)","작곡자":["Teddy","Choice37","Boys Noise"]
,"작사자":"Teddy","길이":"02:11"},
{"트랙번호":"4","곡명":"Stay With Me","작곡자":"G-드래곤","작사자":"G-드래곤","길이":"04:40"},
{"트랙번호":"5","곡명":"아름다워","작곡자":["Teddy","태양","PK","DEE P"],"작사자":"Teddy","길이":"03:27"},
{"트랙번호":"6","곡명":"링가 링가","작곡자":"G-드래곤","작사자":["G-드래곤","토끼"],"길이":"06:11"}],
"그룹":"빅뱅",
"연관검색어":["빅뱅","G-드래곤","양현석","탑"]
}
Modeling Basic
RDBMS vs mongoDB
가수
이름
본명
앨범
앨범명
발매일자
리스트
트랙번호
곡목
소속사
이름
대표자명
그룹
이름
데뷔일자
작곡자
이름
본명
앨범
앨범명
발매일자
가수
이름
본명
리스트
트랙번호
곡목
소속사
이름
대표자명
Modeling Basic
Modeling Step
• 규모 판별 및 예측
• 주요 항목 도출
1단계
분석
• 사용 언어 확정
• 언어별 객체 설계
2단계
설계
• CRUD 개발
• 데이터 전환
• 관리 및 튜닝
3단계
개발 및 운영
Modeling Basic
3 Types
One to Few
One to Many
One to Squilions
Modeling
One to Few
• 하나 당 적은 수
• 한번에 모든 정보를 조회
• UPDATE PUSH를 사용하여 UPSERT
• 내포된 데이터를 다른 데이터와 조합
하여 사용불가
• Sub-document 항목 Update를 위해
선 [_id] 채번을 따로 해야 함
• 마스터성 데이터
Ex) 회원정보, 소셜관계 등
ModelingType I
회원정보
이름
• 홍길동
고향
• 한양어딘가
주소
1
• 국가:조선
• 도시:한양
• 구:마포구
• 지번:상일동 121-2
2
• 국가:대한민국
• 도시:서울
• 구:마포구
• 도로명:상일동 마포길 11
One to Few
• JSON
// 회원
{
name: "홍길동",
hometown: "한양 어딘가",
addresses:
[
{ street: '상일동 121-2', city: '한양', cc: '조선' },
{ streetname: '상일동 마포길 11', city:'서울', cc: '대한민국' }
]
}
ModelingType I
One to Few
• Script – 하나의 주소만 가지고 오기
// first
db.회원.find( {name:"홍길동"}, { addresses: { $slice: 1 } } );
// last
db.회원.find( {name:"홍길동"}, { addresses: { $slice: -1 } } );
ModelingType I
One to Many
• 하나 당 많은 수
• Mother – Child
• Child 에 ObjectID 를 저장
• DB레벨이 아닌 어플리케이션
레벨에서 JOIN 하여 두 문서를
연결
• 각각의 문서를 독자적으로 처리
하여 쉽게 추가/갱신/삭제
• N to N 구조로 확장도 쉽다.
PC
RAM
CPU
HDD
ModelingType I
PARTS
PRODUCT
One to Many
// parts
{ _id: ObjectID('AAAA'),
partno: '123-aff-456',
parttype:'cpu'
name: “Intel Xeon",
qty: 102,
price: 323.22}
{ _id: ObjectID('DEFO'),
partno: '678-xad-123',
parttype:'ram'
name: "Sec DDR4 Memory",
qty: 1321,
price: 99.99
}
// products
{
name: 'WC-3020',
manufacturer: 'MongoPC',
catalog_number: 1234,
parts: [
ObjectID('AAAA'),
ObjectID('DEFO'),
ObjectID('EJFW')
]
}
• JSON
ModelingType I
One to Many
• Script – 조인 처리
// category_number를 기준으로 product를 찾음
product = db.products.findOne({catalog_number: 1234});
// product의 parts 배열에 담긴 모든 parts를 찾음
product_parts = db.parts.find(
{_id: { $in : product.parts } }
).toArray() ;
ModelingType II
One to Squilions
• 하나 당 무지 많은 수
• Mother – Child 라고 할 수 없을 정도로 많은 Child 존재
• 서버에 남는 로그 데이터의 경우 IP 또는 호스트명으로 로그가 쌓임
• mongoDB는 단일 문서의 크기가 16MB를 넘지 못하는 제한이 발생
• Sub-document 에 최소한의 데이터만 저장
ModelingType III
One to Squilions
// host
{
_id : ObjectID('AAAB'),
name : 'goofy.example.com',
ipaddr : '127.66.66.66'
}
// logmsg
{
time : ISODate("2015-09-
02T09:10:09.032Z"),
message : 'cpu is on fire!',
host: ObjectID('AAAB')
}
• JSON
ModelingType III
One to Squilions
• Script – 조인 처리
// 부모 host 문서를 검색
host = db.hosts.findOne({ipaddr : '127.66.66.66'});
// 최근 5000개의 로그를 부모 host의 ObjectID를 이용해 검색
last_5k_msg = db.logmsg.find({host: host._id})
.sort({time : -1})
.limit(5000)
.toArray();
ModelingType III
+3 Types
Two Way Referencing
Many to One & One to Many Denormalization
One to Squilions, Denormalization
Modeling
Two Way Referencing
// person
{
_id: ObjectID("AAF1"),
name: "Koala",
tasks [ // task 문서 참조
ObjectID("ADF9"),
ObjectID("AE02"),
ObjectID("AE73")
]
}
// tasks
{
_id: ObjectID("ADF9"),
description:
"Practice Jiu-jitsu",
due_date: ISODate(
"2015-10-01"),
owner: ObjectID("AAF1")
// person 문서 참조
}
• JSON
Modeling +Type I
Many to One, Denormalization
• JSON
Modeling +Type II
// products
{
name: 'WC-3020',
manufacturer: 'MongoPC',
catalog_number: 1234,
parts: [
ObjectID('AAAA'),
ObjectID('DEFO'),
ObjectID('EJFW')
]
}
// products
{
name: 'WC-3020',
manufacturer: 'MongoPC',
catalog_number: 1234,
parts: [
{ id: ObjectID('AAAA'), name: 'Awesometel
100Ghz CPU' },
{ id: ObjectID('DEFO'), name: 'AwesomeSize
100TB SSD' },
{ id: ObjectID('EJFW'), name: 'Magical Mouse' }
]
}
One to Many, Denormalization
• JSON
Modeling +Type II
// parts
{ _id: ObjectID('AAAA'),
partno: '123-aff-456',
parttype:'cpu'
name: “Intel Xeon",
qty: 102,
price: 323.22}
// parts
{ _id: ObjectID('AAAA'),
partno: '123-aff-456',
parttype:'cpu'
name: “Intel Xeon",
productname: “MongoPC",
product_catalog_number: 1234,
qty: 102,
price: 323.22}
}
One to Squilions, Denormalization
• JSON
Modeling +Type III
// logmsg
{
time : ISODate(
"2015-09-02T09:10:09.032Z"),
message : 'cpu is on fire!',
host: ObjectID('AAAB')
}
// logmsg
{
time : ISODate(
"2015-09-02T09:10:09.032Z"),
message : 'cpu is on fire!',
host: ObjectID('AAAB'),
ipaddr : '127.66.66.66'
}
Modeling Principles
• Unwind is MAGIC!
• 특별한 이유가 없다면 문서에 모두 포함 시킬 것
• 객체에 직접 접근할 필요가 있다면 문서에서 제외 시켜야 함
• Max Document Size 16M
• 배열이 지나치게 크면 안됨
• noSQL is noJOIN
• 어플리케이션에서 JOIN 하는 것을 피하지 말 것
• H/W is cheap one.
• 비정규화는 I/O를 체크해서 CRUD 시 WAIT 발생을 피할 것
• 어플리케이션 레벨에서 어떻게 조회/갱신 할 것인지 고려할 것
Modeling
Operation Tips
• Monitoring ( htop + nmon + mongostat in tmux )
NMONHTOP
mongostat
Operation Tips
• System analysis with NMON
nmon -f -s 60 -c 1440
Operation Tips
• Index Down Sizing
{ _id: ObjectID('AAAA'),
partno: '123-aff-456',
parttype:'cpu'
name: “Intel Xeon Processor E5-4669 v3 (45M Cache, 2.10 GHz)",
qty: 102,
price: 323.22}
{ _id:‘EBDSJDSAH6123AASDLKHJASDFHASDHLK',
partno: '123-aff-456',
parttype:'cpu'
name: “Intel Xeon Processor E5-4669 v3 (45M Cache, 2.10 GHz)",
qty: 102,
price: 323.22}
MD5
parttype+name
Operation Tips
• 기타 주의할 점과 하고 싶은 말
• 인덱스를 구성하는 KEY는 TYPE 가 한결 같이 유지 되어야 한다
ex) IMEI_NO : Character Type 으로 지정 “123456789123”
IP Address : 4 Byte > long 으로 변환 “1.1.1.1”-> 16843009
• 속도가 문제라면 동적 스키마 구성은 잊어라
• UPSERT가 자주 일어나는 문서라면 초기 적재시에 미리 생성
ex) 70분짜리 CD 라면 1초길이의 음악이 4200개 들어갈테니…
• mongoDB 모든 것을 해결?
RDBMS 또는 다른 noSQL 과 혼용하여 사용
ex) REDIS, Spark RDD, Infinispan 등
• 다다익램 (64bit CPU/OS)
• SSD를 꼭 쓰세요! 두번! 세번 쓰세요!!!
• Replication/Sharding/HA-DR/Fail-Over no Comment 입니다.
감사합니다.
https://www.facebook.com/groups/krmug
참조
• 6 Rules of Thumb for MongoDB Schema Design
• http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-
mongodb-schema-design-part-1
• FIFA 온라인 3의 MongoDB 사용기
• http://www.slideshare.net/blahstyle/jwkim-ndc-mongodbfinal
• The MongoDB Strikes Back / MongoDB 의 역습
• http://www.slideshare.net/lqez/the-mongodb-strikes-back-mongodb
• 클라우드 춘추전국시대 서버 개발자 생존기
• http://www.slideshare.net/iFunFactory/ss-55961504

mongoDB 3 type modeling in production

  • 1.
  • 2.
    MongoDB • Document OrientedStorage • JSON 스타일의 Document • 간결하고 강력한 동적 스키마 구성 • Full Index Support • 어느 속성에나 인덱스 설정 가능 • Replication & HighAvailability • LAN과 WAN을 이용한 미러링과 빠른 성능 Introduction
  • 3.
    ROW vs JSON 번호가수명 본명 출생지 소속 연관_01 연관_02 1 태양 동영배 서울 YG 빅뱅 G드래곤 var json = { 가수명 : "태양", 본명 : "동영배", 출생지 : "서울", 소속 : "YG", 연관 : ["빅뱅","G드래곤"] } Introduction
  • 4.
  • 5.
    Terminology RDBMS mongoDB Database Database TableCollection Index Index Row Document Column Field Join Embedding & Linking Primary Key Object _id Introduction $lookup
  • 6.
    Modeling Modeling Basic 3 TypesDocument Storage Model
  • 7.
    RDBMS ERD 테이블_가수 PK 1001 이름태양 본명 동영배 소속 YG 테이블_앨범 PK 2001 FK 1001 앨범명 RISE 발매일 2014.06.03 테이블_곡리스트 PK FK 트랙번호 곡명 작곡자 길이 3001 2001 1 Intro Peejay 01:30 3002 2001 2 눈, 코, 입 Teddy 04:12 3003 2001 3 새벽한시 Teddy 02:11 테이블_그룹 PK 4001 그룹명 빅뱅 소속 YG Modeling Basic
  • 8.
    The JSON isThe Schema { "앨범명":"RISE", "가수명":"태양", "발매일":"2014.06.03", "곡리스트":[ {"트랙번호":"1","곡명":"Intro (RISE)","작곡자":"Peejay","작사자":["타블로","Choice37","태양"],"길이":"01:30"}, {"트랙번호":"2","곡명":"눈코입","작곡자":"Teddy","작사자":"Teddy","길이":"04:12"}, {"트랙번호":"3","곡명":"새벽한시 (1AM)","작곡자":["Teddy","Choice37","Boys Noise"] ,"작사자":"Teddy","길이":"02:11"}, {"트랙번호":"4","곡명":"Stay With Me","작곡자":"G-드래곤","작사자":"G-드래곤","길이":"04:40"}, {"트랙번호":"5","곡명":"아름다워","작곡자":["Teddy","태양","PK","DEE P"],"작사자":"Teddy","길이":"03:27"}, {"트랙번호":"6","곡명":"링가 링가","작곡자":"G-드래곤","작사자":["G-드래곤","토끼"],"길이":"06:11"}], "그룹":"빅뱅", "연관검색어":["빅뱅","G-드래곤","양현석","탑"] } Modeling Basic
  • 9.
  • 10.
    Modeling Step • 규모판별 및 예측 • 주요 항목 도출 1단계 분석 • 사용 언어 확정 • 언어별 객체 설계 2단계 설계 • CRUD 개발 • 데이터 전환 • 관리 및 튜닝 3단계 개발 및 운영 Modeling Basic
  • 11.
    3 Types One toFew One to Many One to Squilions Modeling
  • 12.
    One to Few •하나 당 적은 수 • 한번에 모든 정보를 조회 • UPDATE PUSH를 사용하여 UPSERT • 내포된 데이터를 다른 데이터와 조합 하여 사용불가 • Sub-document 항목 Update를 위해 선 [_id] 채번을 따로 해야 함 • 마스터성 데이터 Ex) 회원정보, 소셜관계 등 ModelingType I 회원정보 이름 • 홍길동 고향 • 한양어딘가 주소 1 • 국가:조선 • 도시:한양 • 구:마포구 • 지번:상일동 121-2 2 • 국가:대한민국 • 도시:서울 • 구:마포구 • 도로명:상일동 마포길 11
  • 13.
    One to Few •JSON // 회원 { name: "홍길동", hometown: "한양 어딘가", addresses: [ { street: '상일동 121-2', city: '한양', cc: '조선' }, { streetname: '상일동 마포길 11', city:'서울', cc: '대한민국' } ] } ModelingType I
  • 14.
    One to Few •Script – 하나의 주소만 가지고 오기 // first db.회원.find( {name:"홍길동"}, { addresses: { $slice: 1 } } ); // last db.회원.find( {name:"홍길동"}, { addresses: { $slice: -1 } } ); ModelingType I
  • 15.
    One to Many •하나 당 많은 수 • Mother – Child • Child 에 ObjectID 를 저장 • DB레벨이 아닌 어플리케이션 레벨에서 JOIN 하여 두 문서를 연결 • 각각의 문서를 독자적으로 처리 하여 쉽게 추가/갱신/삭제 • N to N 구조로 확장도 쉽다. PC RAM CPU HDD ModelingType I PARTS PRODUCT
  • 16.
    One to Many //parts { _id: ObjectID('AAAA'), partno: '123-aff-456', parttype:'cpu' name: “Intel Xeon", qty: 102, price: 323.22} { _id: ObjectID('DEFO'), partno: '678-xad-123', parttype:'ram' name: "Sec DDR4 Memory", qty: 1321, price: 99.99 } // products { name: 'WC-3020', manufacturer: 'MongoPC', catalog_number: 1234, parts: [ ObjectID('AAAA'), ObjectID('DEFO'), ObjectID('EJFW') ] } • JSON ModelingType I
  • 17.
    One to Many •Script – 조인 처리 // category_number를 기준으로 product를 찾음 product = db.products.findOne({catalog_number: 1234}); // product의 parts 배열에 담긴 모든 parts를 찾음 product_parts = db.parts.find( {_id: { $in : product.parts } } ).toArray() ; ModelingType II
  • 18.
    One to Squilions •하나 당 무지 많은 수 • Mother – Child 라고 할 수 없을 정도로 많은 Child 존재 • 서버에 남는 로그 데이터의 경우 IP 또는 호스트명으로 로그가 쌓임 • mongoDB는 단일 문서의 크기가 16MB를 넘지 못하는 제한이 발생 • Sub-document 에 최소한의 데이터만 저장 ModelingType III
  • 19.
    One to Squilions //host { _id : ObjectID('AAAB'), name : 'goofy.example.com', ipaddr : '127.66.66.66' } // logmsg { time : ISODate("2015-09- 02T09:10:09.032Z"), message : 'cpu is on fire!', host: ObjectID('AAAB') } • JSON ModelingType III
  • 20.
    One to Squilions •Script – 조인 처리 // 부모 host 문서를 검색 host = db.hosts.findOne({ipaddr : '127.66.66.66'}); // 최근 5000개의 로그를 부모 host의 ObjectID를 이용해 검색 last_5k_msg = db.logmsg.find({host: host._id}) .sort({time : -1}) .limit(5000) .toArray(); ModelingType III
  • 21.
    +3 Types Two WayReferencing Many to One & One to Many Denormalization One to Squilions, Denormalization Modeling
  • 22.
    Two Way Referencing //person { _id: ObjectID("AAF1"), name: "Koala", tasks [ // task 문서 참조 ObjectID("ADF9"), ObjectID("AE02"), ObjectID("AE73") ] } // tasks { _id: ObjectID("ADF9"), description: "Practice Jiu-jitsu", due_date: ISODate( "2015-10-01"), owner: ObjectID("AAF1") // person 문서 참조 } • JSON Modeling +Type I
  • 23.
    Many to One,Denormalization • JSON Modeling +Type II // products { name: 'WC-3020', manufacturer: 'MongoPC', catalog_number: 1234, parts: [ ObjectID('AAAA'), ObjectID('DEFO'), ObjectID('EJFW') ] } // products { name: 'WC-3020', manufacturer: 'MongoPC', catalog_number: 1234, parts: [ { id: ObjectID('AAAA'), name: 'Awesometel 100Ghz CPU' }, { id: ObjectID('DEFO'), name: 'AwesomeSize 100TB SSD' }, { id: ObjectID('EJFW'), name: 'Magical Mouse' } ] }
  • 24.
    One to Many,Denormalization • JSON Modeling +Type II // parts { _id: ObjectID('AAAA'), partno: '123-aff-456', parttype:'cpu' name: “Intel Xeon", qty: 102, price: 323.22} // parts { _id: ObjectID('AAAA'), partno: '123-aff-456', parttype:'cpu' name: “Intel Xeon", productname: “MongoPC", product_catalog_number: 1234, qty: 102, price: 323.22} }
  • 25.
    One to Squilions,Denormalization • JSON Modeling +Type III // logmsg { time : ISODate( "2015-09-02T09:10:09.032Z"), message : 'cpu is on fire!', host: ObjectID('AAAB') } // logmsg { time : ISODate( "2015-09-02T09:10:09.032Z"), message : 'cpu is on fire!', host: ObjectID('AAAB'), ipaddr : '127.66.66.66' }
  • 26.
    Modeling Principles • Unwindis MAGIC! • 특별한 이유가 없다면 문서에 모두 포함 시킬 것 • 객체에 직접 접근할 필요가 있다면 문서에서 제외 시켜야 함 • Max Document Size 16M • 배열이 지나치게 크면 안됨 • noSQL is noJOIN • 어플리케이션에서 JOIN 하는 것을 피하지 말 것 • H/W is cheap one. • 비정규화는 I/O를 체크해서 CRUD 시 WAIT 발생을 피할 것 • 어플리케이션 레벨에서 어떻게 조회/갱신 할 것인지 고려할 것 Modeling
  • 27.
    Operation Tips • Monitoring( htop + nmon + mongostat in tmux ) NMONHTOP mongostat
  • 28.
    Operation Tips • Systemanalysis with NMON nmon -f -s 60 -c 1440
  • 29.
    Operation Tips • IndexDown Sizing { _id: ObjectID('AAAA'), partno: '123-aff-456', parttype:'cpu' name: “Intel Xeon Processor E5-4669 v3 (45M Cache, 2.10 GHz)", qty: 102, price: 323.22} { _id:‘EBDSJDSAH6123AASDLKHJASDFHASDHLK', partno: '123-aff-456', parttype:'cpu' name: “Intel Xeon Processor E5-4669 v3 (45M Cache, 2.10 GHz)", qty: 102, price: 323.22} MD5 parttype+name
  • 30.
    Operation Tips • 기타주의할 점과 하고 싶은 말 • 인덱스를 구성하는 KEY는 TYPE 가 한결 같이 유지 되어야 한다 ex) IMEI_NO : Character Type 으로 지정 “123456789123” IP Address : 4 Byte > long 으로 변환 “1.1.1.1”-> 16843009 • 속도가 문제라면 동적 스키마 구성은 잊어라 • UPSERT가 자주 일어나는 문서라면 초기 적재시에 미리 생성 ex) 70분짜리 CD 라면 1초길이의 음악이 4200개 들어갈테니… • mongoDB 모든 것을 해결? RDBMS 또는 다른 noSQL 과 혼용하여 사용 ex) REDIS, Spark RDD, Infinispan 등 • 다다익램 (64bit CPU/OS) • SSD를 꼭 쓰세요! 두번! 세번 쓰세요!!! • Replication/Sharding/HA-DR/Fail-Over no Comment 입니다.
  • 31.
  • 32.
    참조 • 6 Rulesof Thumb for MongoDB Schema Design • http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for- mongodb-schema-design-part-1 • FIFA 온라인 3의 MongoDB 사용기 • http://www.slideshare.net/blahstyle/jwkim-ndc-mongodbfinal • The MongoDB Strikes Back / MongoDB 의 역습 • http://www.slideshare.net/lqez/the-mongodb-strikes-back-mongodb • 클라우드 춘추전국시대 서버 개발자 생존기 • http://www.slideshare.net/iFunFactory/ss-55961504