代码之家  ›  专栏  ›  技术社区  ›  brad

MongoDB设计,嵌入vs关系

  •  21
  • brad  · 技术社区  · 14 年前

    我正在构建一个简单的会计系统,用户有许多账单。现在,我正试图决定账单应该是它自己的集合,还是嵌套在用户内部。我倾向于前者,但我从来没有做过任何NoSQL的事情,所以我只是在尝试和错误,以及我认为对我有意义的东西。

    我知道Mongo有一个4MB的文档大小限制,这让我觉得应该单独收集账单,因为这些账单每天都会累积,最终可能占用大量空间。

    我只是在征求意见。基本上,我将在不同的日期期间查询用户的账单(正如您可以想象的那样,会计系统会这样做)。

    这并不重要,但我在Rails3项目中使用MongoID。我想我会做如下的事情:

    class User
      references_many :bills
    end
    
    class Bill
      referenced_in :user
    end
    

    如有任何意见或设计建议,我们将不胜感激。

    3 回复  |  直到 7 年前
        1
  •  24
  •   srivani    14 年前

    1)关于4MB文件限制,这是“MongoDB:最终指南”所说的:

    大于4MB的文档(转换为BSON时)无法保存到数据库中。这是一个有点武断的限制(将来可能会提高);它主要是为了防止错误的模式设计并确保一致的性能。查看文档的bson大小(字节) doc ,运行object.bsonSize( doc )从外壳上。

    为了让你知道4MB是多少,整个文本 战争与和平 只有3.14MB。

    最后,这取决于您对用户的账单增长预期有多大。我希望上面的摘录能让您了解文档大小所施加的限制。

    2)如果您知道永远不会对账单运行全局查询,则可以使用非规范化模式(账单与用户文档一起使用),例如,如果您希望检索输入到系统中的十个最新账单,则可以使用这种查询。如果使用非规范化模式,则必须使用map reduce来检索此类查询的结果。

    如果您希望在如何查询账单方面具有灵活性,规范化模式(用户和单独文档中的账单)是更好的选择。但是,由于MongoDB不支持联接,因此每次需要检索与用户对应的账单时,都必须运行多个查询。

    考虑到您提到的用例,我将使用非规范化模式。

    3)MongoDB中的所有更新都是原子更新和序列化的。这应该回答史蒂夫的问题。

    您可能会发现这些幻灯片很有用。 http://www.slideshare.net/kbanker/mongodb-meetup

    您还可以查看MongoDB的生产部署页面。您可能会发现sf.net幻灯片很有用。

        2
  •  1
  •   Steve B.    14 年前

    您可能想考虑的一个问题是,是否会有一段时间,除了用户的成员资格之外,您还需要单独参考账单?如果是这样的话,如果他们有一个独立的存在就简单了。

    除此之外,您已经确定的尺寸限制问题是将它们分开的一个很好的理由。

    也可能存在事务性问题,如果您正在编写一个包含许多帐单的大用户,那么如果您从不同的连接中合理地同时向同一个用户写入更改,会发生什么情况?我不太了解Mongo,不知道它会如何解决这个问题-我想如果写的内容包含不同的附加账单,你会同时得到它们,但是如果它们包含现有账单的不同更改,你会被覆盖-希望其他人对此发表评论,但是至少我会测试一下。如果你把账单写在一个单独的托收上,这不是一个问题。

        3
  •  1
  •   Dan L    13 年前

    这个问题已经解决很久了,但是我正在处理类似的事情,我想我会为其他研究这个问题的人添加我的发现。

    我的理解是4MB文档在1.8+版本中已扩展到16MB。这是MongoDB成员之一Banker的视频演示。我还没有验证这个值,但我相信他的话(因为他希望知道他在说什么)。

    关于在同一个用户上发生多个带有嵌入式账单的更新时会发生什么的问题……同样,从同一个视频演示中,提供的答案是MongoDB更新信息的速度非常快,这通常不是问题。MongoDB实例在进行更新时被锁定,因此不应出现多个更新问题。

    我对嵌入文档的一个担心是不能独立于父文档来处理它们。在我看来,这使得嵌入式文档变得毫无价值。它们只对满足特定用例的特定案例有用。

    我个人发现MongoDB(和NoSQL DBS)对于特定的情况很有用,但是传统的SQL/RDMS对于大多数问题仍然更好。如果您是Craigslist这样的人,并且模式更改需要2个月才能运行存档数据,那么是的,MongoDB和NoSQL是有意义的。但是对于绝大多数应用程序来说,我认为处理这么多的数据并不是一个主要问题。