[MongoDB] Modeling 3.Extended Reference Pattern

기훈·2024년 4월 5일

MongoDB

목록 보기
6/28

회원이 많은 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");
    
  • 분석 및 결과

    • 조회시 331ms 시간이 소요됐고 대부분이 조인에의한 것이였다.
    • 인덱스를 추가했음에도 오히려 시간이 더 소요됐다. (442ms)

개선하기

  • 컬렉션을 분리 후 내장시킬 수 있는 필드를 일부 내장시킨다. (변경되지 않거나 꼭 함께 조회해야 하는 필드)

    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), 인덱스를 설정하면 조회시간이 더욱 단축된다.

0개의 댓글