회원이 많은 OLTP성 카페의 요구사항을 구현하고 모델링을 진행 해보자.
3. 도큐먼트가 16메가바이트를 넘는 문제 + 카페에 대한 데이터가 수정될 때, 작업시간이 선형적으로 증가하는 문제 해결 하기 위해 컬렉션을 분리한다.
cafe와 members 컬렉션을 각각 생성한다
db.cafe.insertMany([
{
_id: 1,
name: "IT Community",
desc: "A Cafe where developer's share information.",
created_at: ISODate("2018-08-09"),
last_article: ISODate("2022-06-01T10:56:32.000Z"),
level: 5,
},
{
_id: 2,
name: "Game Community",
desc: "Share information about games.",
created_at: ISODate("2020-01-23"),
last_article: ISODate("2022-06-02T10:56:32.000Z"),
level: 4,
},
]);
db.members.insertMany([
{
id: "tom93",
first_name: "Tom",
last_name: "Park",
phone: "000-0000-1234",
job: "DBA",
joined_cafes: [1, 2],
},
{
id: "asddwd12",
first_name: "Jenny",
last_name: "Kim",
phone: "000-0000-1111",
job: "Frontend Dev",
joined_cafes: [1, 2],
},
{
id: "candy12",
first_name: "Zen",
last_name: "Ko",
phone: "000-0000-1233",
job: "DA",
joined_cafes: [1],
},
{
id: "java1",
first_name: "Kevin",
last_name: "Shin",
phone: "000-0000-1133",
job: "Game Dev",
joined_cafes: [2],
},
]);
두 가지의 문제는 해결했지만, 데이터 조회시 조인이 발생한다. 30만명의 유저를 추가하고 조회 시간을 분석 해보자
db.cafe
.aggregate([
{
$lookup: {
from: "members",
localField: "_id",
foreignField: "joined_cafes",
as: "members",
pipeline: [
{
$match: {
job: "DBA",
},
},
{
$project: {
_id: 0,
id: 1,
job: 1,
},
},
],
},
},
{
$project: {
name: 1,
desc: 1,
created_at: 1,
joinedMemberJob: {
$first: "$members.job",
},
cnt: {
$size: "$members",
},
},
},
]).explain("executionStats");
분석 및 결과
개선하기
컬렉션을 분리 후 내장시킬 수 있는 필드를 일부 내장시킨다. (변경되지 않거나 꼭 함께 조회해야 하는 필드)
db.cafe.insertMany([
{
_id: 1,
name: "IT Community",
desc: "A Cafe where developer's share information.",
created_at: ISODate("2018-08-09"),
last_article: ISODate("2022-06-01T10:56:32.000Z"),
level: 5,
},
{
_id: 2,
name: "Game Community",
desc: "Share information about games.",
created_at: ISODate("2020-01-23"),
last_article: ISODate("2022-06-02T10:56:32.000Z"),
level: 4,
},
]);
db.members.insertMany([
{
id: "tom93",
first_name: "Tom",
last_name: "Park",
phone: "000-0000-1234",
job: "DBA",
joined_cafes: [
{
_id: 1,
name: "IT Community",
desc: "A Cafe where developer's share information.",
created_at: ISODate("2018-08-09"),
},
{
_id: 2,
name: "Game Community",
desc: "Share information about games.",
created_at: ISODate("2020-01-23"),
},
],
},
{
id: "asddwd12",
first_name: "Jenny",
last_name: "Kim",
phone: "000-0000-1111",
job: "Frontend Dev",
joined_cafes: [
{
_id: 1,
name: "IT Community",
desc: "A Cafe where developer's share information.",
created_at: ISODate("2018-08-09"),
},
{
_id: 2,
name: "Game Community",
desc: "Share information about games.",
created_at: ISODate("2020-01-23"),
},
],
},
{
id: "candy12",
first_name: "Zen",
last_name: "Ko",
phone: "000-0000-1233",
job: "DA",
joined_cafes: [
{
_id: 1,
name: "IT Community",
desc: "A Cafe where developer's share information.",
created_at: ISODate("2018-08-09"),
},
],
},
{
id: "java1",
first_name: "Kevin",
last_name: "Shin",
phone: "000-0000-1133",
job: "Game Dev",
joined_cafes: [
{
_id: 2,
name: "Game Community",
desc: "Share information about games.",
created_at: ISODate("2020-01-23"),
},
],
},
]);
데이터 조회결과 이전에 비해 개선이 된 것을 볼 수 있다(220ms), 인덱스를 설정하면 조회시간이 더욱 단축된다.