MongoDB架构devise – 许多小文件或更less的大文件?

背景
我正在将从RDBMS数据库到MongoDB的转换原型化。 在反规范化的过程中,好像我有两个select,一个导致许多(百万)较小的文档或一个导致较less(几十万)大文档的select。

如果我可以把它简化为一个简单的模拟,那么这个集合与这样一个更less的Customer文档(用Java)是有区别的:

 class Customer {
    私人string名称;
    私人地址地址;
     //每个CreditCard都有数百个付款实例
    私人设置<CreditCard> creditCards;
 }

或许多像这样的许多付款文件的集合:

class付款{
    私人客户客户;
    私人CreditCard信用卡;
    私人datepayDate;
    私人stream通payAmount;
 }


MongoDB的devise是为了select许多小文档还是less用大文档? 答案主要取决于我计划运行的查询吗? (即客户X有多less张信用卡?vs上个月所有客户的平均金额是多less?

我查了很多,但是我没有绊倒任何可以帮助我回答我的问题的MongoDB模式最佳实践。

你一定要优化你正在做的查询。

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

您可能想知道每个客户的所有信用卡,因此请保留客户对象内的数组。 您也可能希望为每个付款提供客户参考。 这将使付款文件相对较小。

Payment对象将自动拥有自己的ID和索引。 您可能还需要在“客户”参考中添加一个索引。

这将允许您快速search客户付款,而不必每次都存储整个客户对象。

如果您想回答“所有客户上个月支付的平均金额是多less”这样的问题,那么您将需要为任何相当大的数据集devise一个地图/缩减。 你没有得到这个“实时”的回应。 你会发现存储一个“参考”到客户可能是足够的这些地图缩小。

所以要直接回答你的问题: 是否MongoDBdevise成偏好许多小文档或更less的大文档?

MongoDB旨在快速查找索引条目。 MongoDB非常擅长在大海捞针中find几根针。 MongoDB 并不是很擅长find大海捞针。 因此,围绕最常见的用例构build数据,并为罕见用例编写map / reduce作业。

根据MongoDB自己的文档,这听起来像是为许多小文档devise的。

从MongoDB的性能最佳实践 :

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

从MongoDB Schemadevise的6条经验法则:第1部分 :

build模一对多

“一对一”的例子可能是一个人的地址。 这是embedded的一个很好的例子 – 你将地址放在Person对象的数组中。

一个一对多

“一对多”的例子可能是replace零件订购系统中产品的零件。 每个产品可能有多达几百个replace部件,但从未超过几千个左右。 这是引用的一个很好的用例 – 您将产品文档中的部分的ObjectIDs放在一个数组中。

一到Squillions

“一对一”的例子可能是事件logging系统,它为不同的机器收集日志消息。 任何给定的主机都可以生成足够的消息来溢出16 MB的文档大小,即使您存储在arrays中的所有内容都是ObjectID。 这是“父引用”的经典用例 – 您需要为主机创build一个文档,然后将主机的ObjectID存储在日志消息的文档中。

随着时间的推移,大量增长的文件可能正在计时炸弹。 networking带宽和内存使用量可能会成为可衡量的瓶颈,迫使您重新开始。

首先,我们来考虑两个集合:Customer和Payment。 因此,粮食是相当小的:每笔支付一个文件。

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

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

您的决定影响付款文件。 如果帐户信息embedded到客户文档中,您会如何参考? 单独的账户文件有自己的_id属性。 使用embedded式帐户信息,您的应用程序将为帐户​​生成新的ID,或使用帐户的密钥属性(例如,帐户号码)。

付款凭证是否可以包含在固定时间范围内(例如,每天?)进行的所有付款。 这种复杂性会影响所有读取和写入付款文件的代码。 不成熟的优化对项目来说可能是致命的。

与帐户凭证一样,只要付款凭证只包含一笔付款,便可轻易引用付款。 例如,新的文件types可以参考付款。 但是,你会创build一个信用卡collections品,还是将信用信息embedded付款信息? 如果你以后需要引用信用,会发生什么?

总而言之,我已经获得了许多小文件和许多collections。 我用_id实现引用,只用_id实现引用。 因此,我不担心日益增长的文件摧毁我的申请。 模式很容易理解和索引,因为每个实体都有自己的集合。 重要的实体不会隐藏在其他文档中。

我很想听听你的发现。 祝你好运!