当前位置:  开发笔记 > 数据库 > 正文

MongoDB架构设计 - 许多小文档或更少的大型文档?

如何解决《MongoDB架构设计-许多小文档或更少的大型文档?》经验,为你挑选了3个好方法。

背景
我正在从我们的RDBMS数据库到MongoDB的转换原型.在非规范化的过程中,似乎我有两个选择,一个导致许多(数百万)较小的文档,或者一个导致较少(数十万)大文档.

如果我可以将它提炼成一个简单的模拟,那么具有较少客户文档的集合(如Java)之间的区别是:

class Customer {
    private String name;
    private Address address;
    // each CreditCard has hundreds of Payment instances
    private Set creditCards;
}

或者包含许多许多付款文件的集合,如下所示:

class Payment {
    private Customer customer;
    private CreditCard creditCard;
    private Date payDate;
    private float payAmount;
}

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

我已经环顾了很多,但我没有偶然发现任何可以帮助我回答我的问题的MongoDB架构最佳实践.



1> Gates VP..:

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

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

您可能想知道每个客户的所有信用卡,因此请在客户对象中保留一组信用卡.您可能还希望为每个付款设置一个客户参考.这将使付款文件相对较小.

Payment对象将自动拥有自己的ID和索引.您可能还想在Customer引用上添加索引.

这将允许您快速搜索客户付款,而无需每次都存储整个客户对象.

如果您想回答诸如"上个月所有客户支付的平均金额是多少"这样的问题,那么您需要为任何规模较大的数据集寻找地图/缩减.你没有"实时"得到这个回应.你会发现存储一个"引用"给客户可能足以让这些地图减少.

所以直接回答你的问题:MongoDB是否设计为偏好许多很小的文档或更少的大文档?

MongoDB旨在快速查找索引条目.MongoDB非常擅长在大型干草堆中找到几根针.MongoDB 不是很擅长在大海捞针中找到大部分针头.因此,围绕最常见的用例构建数据,并为罕见的用例编写map/reduce作业.



2> bmaupin..:

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

来自MongoDB的性能最佳实践:

MongoDB中文档的最大大小为16 MB.实际上,大多数文档都是几千字节或更少.考虑更像表格中的行而不是表格本身的文档.而不是在单个文档中维护记录列表,而是将每个记录作为文档.

来自6个MongoDB架构设计的经验法则:第1部分:

建模一对一

"一对一"的例子可能是一个人的地址.这是嵌入的一个很好的用例 - 你将地址放在Person对象的数组中.

一个一对多

"一对多"的示例可以是替换零件订购系统中的产品的零件.每个产品可能有多达几百个替换零件,但从不超过几千个左右.这是一个很好的引用用例 - 您可以将部件的ObjectID放在产品文档的数组中.

一到Squillions

"one-to-squillions"的示例可能是一个事件记录系统,它收集不同计算机的日志消息.即使您存储在数组中的所有内容都是ObjectID,任何给定的主机都可以生成足够的消息来溢出16 MB的文档大小.这是"父引用"的经典用例 - 您有一个主机文档,然后将主机的ObjectID存储在日志消息的文档中.



3> Terris..:

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

首先,让我们考虑两个集合:客户和付款.因此,粮食相当小:每次付款一份文件.

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

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

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

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

与帐户文档一样,只要付款单据只包含一笔付款,就可以轻松引用付款.例如,一种新类型的文档可以引用付款.但是,您是否会创建一个信用卡集合,或者您是否将信用信息嵌入到付款信息中?如果您以后需要参考信用证会怎么样?

总而言之,我成功地获得了许多小文档和许多集合.我用_id实现引用,只用_id实现.因此,我不担心不断增长的文档会破坏我的应用程序.模式易于理解和索引,因为每个实体都有自己的集合.重要实体不会隐藏在其他文档中.

我很想知道你的发现.祝好运!

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有