MongoDB Schema Design-很多小文件还是更少的大文件?


87

背景信息
我正在建立从RDBMS数据库到MongoDB的转换的原型。在进行非规范化时,似乎我有两种选择,一种选择导致许多(数百万)个较小的文档,另一种选择导致较少的(数十万个)大型文档。

如果我可以将其简化为一个简单的类比,那将是具有这样的更少Customer文档的集合之间的区别(在Java中):

客户类别{
    私有字符串名称;
    私人地址;
    //每个信用卡都有数百个付款实例
    私人Set <CreditCard>信用卡;
}

或具有许多付款文件的集合,例如:

类别付款{
    私人客户客户;
    私人CreditCard信用卡;
    私人Date payDate;
    私人浮动工资
}

问题
MongoDB是设计为首选许多文档还是更少的大型文档?答案是否主要取决于我计划运行的查询?(即,客户X有多少张信用卡?vs所有客户上个月平均支付的金额是多少?)

我到处走走了很多,但是我没有发现任何可帮助我回答问题的MongoDB模式最佳实践。

Answers:


81

您肯定需要针对正在执行的查询进行优化。

根据您的描述,这是我最好的猜测。

您可能想知道每个客户的所有信用卡,因此请在“客户对象”中保留一系列信用卡。您可能还需要每个付款的客户参考。这将使付款单据相对较小。

Payment对象将自动具有其自己的ID和索引。您可能还希望在“客户”引用上添加索引。

这样,您便可以快速搜索“客户付款”,而不必每次都存储整个客户对象。

如果您要回答“上个月所有客户平均支付的金额是多少”之类的问题,您将需要一个地图/缩减任何可观的数据集。您没有“实时”获得此响应。您会发现,对于这些map-reduce,存储对Customer的“引用”可能就足够了。

因此,直接回答您的问题:MongoDB是设计为偏爱许多很多小文档还是更少的大型文档?

MongoDB旨在非常快速地找到索引条目。MongoDB非常擅长在大海捞针中找到几根针。MongoDB是不是在寻找很好大部分的针在草堆。因此,围绕最常见的用例构建数据,并为罕见的用例编写映射/减少作业。


30

根据MongoDB自己的文档,听起来它是为许多小型文档设计的。

来自MongoDB的性能最佳实践

MongoDB中文档的最大大小为16 MB。实际上,大多数文档为几千字节或更小。考虑文档比表本身更像表中的行。而不是维护单个文档中的记录列表,而是使每个记录成为一个文档。

拇指的MongoDB架构设计的6个规则:第1部分

少量建模

一个“很少”的例子可能是一个人的地址。这是嵌入的好用例-您将地址放入Person对象内的数组中。

一对多

“一对多”的示例可能是替换零件订购系统中产品的零件。每个产品最多可具有数百个替换零件,但最多不超过几千个。这是一个很好的参考用例–您已将零件的ObjectID放在产品文档中的数组中。

一对一

事件记录系统可以收集不同机器的日志消息,例如“一到十亿”。任何给定的主机都可以生成足够的消息,以溢出16 MB的文档大小,即使您存储在阵列中的只是ObjectID。这是“父级引用”的经典用例-您将拥有主机的文档,然后将主机的ObjectID存储在日志消息的文档中。


11

随着时间的推移而大量增长的文档可能是定时炸弹。网络带宽和RAM使用可能会成为可衡量的瓶颈,从而迫使您重新开始。

首先,让我们考虑两个集合:客户和付款。因此,谷物的数量非常小:每次付款仅一份文件。

接下来,您必须决定如何对帐户信息(例如信用卡)建模。让我们考虑客户文档是否包含帐户信息数组,或者是否需要新的帐户集合。

如果帐户文档与客户文档分开,则将一个客户的所有帐户加载到内存中需要提取多个文档。这可能会转化为额外的内存,I / O,带宽和CPU使用率。这是否立即意味着“帐户收款”是个坏主意?

您的决定会影响付款文件。如果客户信息嵌入客户文档中,您将如何引用它?单独的帐户文档具有自己的_id属性。使用嵌入的帐户信息,您的应用程序将为帐户​​生成新的ID或将帐户的属性(例如,帐户编号)用作密钥。

付款凭证实际上是否可以包含在固定时间范围内(例如,一天?)进行的所有付款。这种复杂性将影响所有读取和写入付款单据的代码。过早的优化对项目可能是致命的。

与帐户单据一样,只要付款单据仅包含一笔付款,就可以轻松地参考付款。新型文件(例如贷方)可以引用付款。但是,您将创建一个信用集合还是将信用信息嵌入付款信息中?如果您以后需要引用信用证会怎样?

总而言之,我已经成功完成了许多小文档和许多收藏。我使用_id且仅使用_id来实现引用。因此,我不必担心不断增长的文档会破坏我的应用程序。由于每个实体都有其自己的集合,因此该架构易于理解和建立索引。重要实体没有隐藏在其他文档中。

我希望知道您的发现。祝好运!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.