mongodb 3 type modeling in production
TRANSCRIPT
Modeling
Facebook mongoDB Korea 김동한
MongoDB
• Document Oriented Storage• JSON 스타일의 Document• 간결하고 강력한 동적 스키마 구성
• Full Index Support• 어느 속성에나 인덱스 설정 가능
• Replication & High Availability• LAN 과 WAN 을 이용한 미러링과 빠른 성능
Introduction
ROW vs JSON
번호 가수명 본명 출생지 소속 연관_01 연관 _02
1 태양 동영배 서울 YG 빅뱅 G 드래곤 var json = { 가수명 : " 태양 ", 본명 : " 동영배 ", 출생지 : " 서울 ", 소속 : "YG", 연관 : [" 빅뱅 ","G 드래곤 "] }
Introduction
mongoDB 구조
{JSON} COLLECTION
DATABASE
Introduction
TerminologyRDBMS mongoDB
Database Database
Table Collection
Index Index
Row Document
Column Field
Join Embedding & Linking
Primary Key Object _id
Introduction
$lookup
ModelingModeling 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:303002 2001 2 눈 , 코 , 입 Teddy 04:123003 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 TypesOne to Few
One to Many
One to Squilions
Modeling
One to Few
• 하나 당 적은 수
• 한번에 모든 정보를 조회
• UPDATE PUSH 를 사용하여 UPSERT
• 내포된 데이터를 다른 데이터와 조합하여 사용불가
• Sub-document 항목 Update 를 위해선 [_id] 채번을 따로 해야 함
• 마스터성 데이터Ex) 회원정보 , 소셜관계 등
Modeling Type I
회원정보이름• 홍길동
고향• 한양어딘가
주소1• 국가 : 조선• 도시 : 한양• 구 : 마포구• 지번 : 상일동 121-2
2• 국가 : 대한민국• 도시 : 서울• 구 : 마포구• 도로명 : 상일동 마포길
11
One to Few
• JSON
// 회원{ name: " 홍길동 ", hometown: " 한양 어딘가 ", addresses: [ { street: ' 상일동 121-2', city: ' 한양 ', cc: ' 조선 ' }, { streetname: ' 상일동 마포길 11', city: '서울 ', cc: '대한민국 ' } ]}
Modeling Type I
One to Few
• Script – 하나의 주소만 가지고 오기
// firstdb. 회원 .find( {name:" 홍길동 "}, { addresses: { $slice: 1 } } );
// lastdb. 회원 .find( {name:" 홍길동 "}, { addresses: { $slice: -1 } } );
Modeling Type I
One to Many
• 하나 당 많은 수
• Mother – Child
• Child 에 ObjectID 를 저장
• DB 레벨이 아닌 어플리케이션 레벨에서 JOIN 하여 두 문서를 연결
• 각각의 문서를 독자적으로 처리하여 쉽게 추가 / 갱신 /삭제
• N to N 구조로 확장도 쉽다 .
PC
RAM
CPUHDD
Modeling Type 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
Modeling Type 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() ;
Modeling Type II
One to Squilions
• 하나 당 무지 많은 수
• Mother – Child 라고 할 수 없을 정도로 많은 Child 존재
• 서버에 남는 로그 데이터의 경우 IP 또는 호스트명으로 로그가 쌓임
• mongoDB 는 단일 문서의 크기가 16MB 를 넘지 못하는 제한이 발생
• Sub-document 에 최소한의 데이터만 저장
Modeling Type 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
Modeling Type 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();
Modeling Type III
+3 TypesTwo 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-mon
godb
• 클라우드 춘추전국시대 서버 개발자 생존기• http://www.slideshare.net/iFunFactory/ss-55961504