mongodb中的数据重复过多?


74

我是整个NOSQL的新手,最近对mongoDB感兴趣。我正在从头开始创建一个新网站,并决定将MONGODB / NORM(用于C#)作为我的唯一数据库。我已经阅读了很多有关如何正确设计文档模型数据库的文章,并且我认为在大多数情况下我的设计工作都很好。我到新站点大约需要6个月的时间,并且开始发现需要重复处理的数据重复/同步问题。根据我的阅读,这在文档模型中是可以预期的,并且对于性能而言,这是有意义的。IE,您将嵌入的对象粘贴到文档中,因此读取速度很快-无联接;但是当然不能总是嵌入,因此mongodb具有DbReference的概念,该概念基本上类似于关系数据库中的外键。

所以这是一个例子:我有用户和事件;两者都有自己的文档,用户参加事件,事件都有用户参加。我决定将带有有限数据的事件列表嵌入到User对象中。我还将用户列表作为其“参与者”也嵌入到Event对象中。现在的问题是,我必须使Users与也嵌入在Event对象中的Users列表保持同步。在我阅读本文时,这似乎是首选方法,也是NOSQL做事的方法。检索速度很快,但是在我更新主用户文档时就遇到了麻烦,我还需要进入Event对象,可能会找到对该用户的所有引用并进行更新。

所以我的问题是,这是人们需要处理的一个非常普遍的问题吗?在您开始说“也许NOSQL策略不适合我在此试图做的事情”之前,这个问题必须发生多少?何时不必进行连接而带来的性能优势何时变成劣势,因为您很难使数据在嵌入式对象中保持同步,并且很难对数据库进行多次读取呢?


这是有关MongoDB中数据冗余另一个问题。我的回答是建议使用map-reduce输出作为缓存,而不是单独的缓存层。如果您可以使用过时的数据,这可能会很有用。请注意,数据的新鲜度取决于您执行映射减少作业的频率,例如每15分钟运行一次。
Niels van der Rest 2010年

DBReference是邪恶的,它夺走了大多数NoSQL的魅力
Rahul Kumar

Answers:


63

好吧,这就是与文档存储的权衡。您可以像任何标准RDMS一样以规范化的方式进行存储,并且应尽可能地进行规范化。只有在它影响性能的情况下,您才应该打破规范化并展平数据结构。需要权衡的是读取效率与更新成本。

Mongo具有真正有效的索引,可以像传统的RDMS一样使归一化更加容易(大多数文档存储都不免费提供给您,这就是为什么Mongo更像是一种混合而不是纯文档存储)。使用此功能,可以在用户和事件之间建立关系集合。它类似于表格数据存储中的代理表。为事件和用户字段建立索引,它应该很快,并且可以帮助您更好地规范化数据。

我喜欢绘制扁平化结构的效率与保持结构规范化的效率,这涉及到我更新记录数据所需的时间与读出查询中需要的时间。您可以使用大号O表示法来做到这一点,但不必那么花哨。只需根据几个具有不同数据模型的用例在纸上写下一些数字,就可以知道需要多少工作量。

基本上,我要做的是首先尝试预测一条记录将进行多少次更新与读取一次的概率。然后,我尝试预测将更新标准化或展平时(或也许我可以设想的两者的一部分……很多优化选项)相比较,读取与读取的成本是多少。然后,我可以判断保持平坦状态所节省的费用,以及从规范化源构建数据的成本。一旦绘制了所有变量,如果保持平整的节省节省了我一堆,那么我将保持平整。

一些提示:

  • 如果您需要快速且快速且原子化的查询(完全最新),则可能需要一种解决方案,其中您希望扁平化而不是规范化,并希望获得更新。
  • 如果您需要快速更新,并立即访问,请支持规范化。
  • 如果您需要快速查找但又不需要最新数据,则可以考虑在批处理作业中建立标准化数据(可能使用map / reduce)。
  • 如果您的查询需要快速进行,并且更新很少见,并且不一定要求您的更新必须立即可用或需要事务级别锁定(必须经过100%的时间进行锁定)(以确保将更新写入磁盘),您可以可以考虑将更新写入到在后台处理更新的队列中。(在此模型中,您稍后可能必须处理冲突解决和和解)。
  • 剖析不同的模型。在代码中构建一个数据查询抽象层(某种程度上类似于ORM),以便以后可以重构数据存储结构。

您还可以采用许多其他想法。网上有很多很棒的博客,例如highscalabilty.org,可以确保您了解CAP定理。

还考虑缓存层,例如Redis或memcache。我将其中一种产品放在数据层的前面。当我查询mongo(存储所有归一化的东西)时,我使用数据构造一个扁平化的表示并将其存储在缓存中。更新数据时,会使引用我要更新的内容的缓存中的所有数据无效。(尽管您必须花一些时间来使数据无效并跟踪正在更新的高速缓存中的数据,这已经考虑到了缩放因子)。有人曾经说过:“计算机科学中最困难的两件事是命名事物和缓存失效。”

希望有帮助!


感谢您的回复!很多好的见解/建议!我还没有想到用户事件关系集合。缓存绝对是我将来必须考虑的事情。
mike 2010年

+1用于引入代理表。这将导致在单个位置定义文档之间的关系,而不是两个。@mike:我想指出DBRef只是一个正式规范,它不像外键那样神奇:)引用也必须像复制数据一样手动维护。因此,我不建议您“尽可能争取标准化”。
Niels van der Rest 2010年

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.