mongodb中的数据重复太多了?

我是新来的整个NOSQL的东西,最近一直对mongoDB感兴趣。 我从头开始创build一个新的网站,并决定将MONGODB / NORM(用于C#)作为我唯一的数据库。 我一直在阅读很多关于如何正确devise你的文档模型数据库的问题,而且我认为我的devise在很大程度上是相当成功的。 我在我的新网站大约6个月,我开始看到数据重复/同步的问题,我需要处理一遍又一遍。 从我所读到的,这在文档模型中是可以预料的,而对于性能来说它是有意义的。 IE浏览器将embedded式对象粘贴到文档中,因此读取速度快 – 无需连接; 但是当然你不能总是embedded,所以mongodb有这个DbReference的概念,它基本上和关系DB中的外键类似。

所以这里有一个例子:我有用户和事件; 既获得自己的文件,用户参加活动,活动有用户与会者。 我决定将有限数据的事件列表embedded到用户对象中。 我也将用户列表embeddedEvent对象中作为他们的“参与者”。 现在的问题是我必须保持用户与同样embedded在Event对象中的用户列表同步。 正如我所读到的,这似乎是首选方法,而NOSQL方式是做事情的。 检索速度很快,但后退是当我更新主要的用户文档,我需要也进入事件对象,可能find所有引用到该用户,并更新。

所以我的问题是,这是一个很普遍的问题,人们需要处理? 在开始说“也许NOSQL策略不符合我在这里要做的事情”之前,这个问题要发生多less? 什么时候不需要做连接的性能优势变成了一个劣势,因为你很难在embedded对象中保持数据同步并对数据库执行多次读取操作?

那么这是与文件商店的交易。 您可以像任何标准的RDMS一样以标准化的方式进行存储,并尽可能地争取标准化。 只有在性能受到影响的情况下,才能打破规范化,扁平化数据结构。 权衡是读取效率与更新成本。

Mongo具有非常高效的索引,可以像传统的RDMS一样简单地进行规范化(大多数文档商店不会免费提供这个function,这就是为什么Mongo更像是一个混合而不是纯文档存储)。 使用这个,你可以在用户和事件之间build立一个关系集合。 这类似于表格数据存储中的代理表。 索引事件和用户字段,它应该很快,并将帮助您更好地规范化您的数据。

我喜欢绘制一个结构平坦化的效率,同时在需要更新logging数据和读取我需要的时间的时候保持它的正常化。 你可以用大O符号来做,但是你不必是那么想的。 只需要根据一些使用不同模型的用例对数据进行一些简单的数据分析,并得到需要多less工作的良好感觉。

基本上,我所做的是首先尝试预测一个logging有多less次更新的概率,以及它被读取的频率。 然后,我试着预测更新的成本与标准化或扁平化(或者两者的部分组合)的更新成本相比,我可以设想…许多优化选项。 然后,我可以判断保持平衡的成本与从规范化来源构build数据的成本。 一旦我绘制了所有的variables,如果保持平坦的节约可以节省我一大笔钱,那么我会保持平稳。

一些提示:

  • 如果您需要快速查找快速和primefaces级(完美的最新),您可能希望得到一个解决scheme,在这种情况下,您更喜欢使标准化变得更加平坦化,并使更新受到打击。
  • 如果你需要更新很快,并立即访问,那么有利于正常化。
  • 如果您需要快速查找,但不需要完美的最新数据,请考虑在批处理作业中构build标准化数据(可能使用map / reduce)。
  • 如果您的查询需要快速,并且更新很less,并且不一定要求您的更新立即可访问,或者需要事务级别locking(100%的时间来保证您的更新已写入磁盘),那么您可以考虑把你的更新写入一个队列中,在后台处理它们。 (在这个模型中,您可能需要稍后处理冲突解决和和解)。
  • configuration不同的型号。 在你的代码中build立一个数据查询抽象层(就像一个ORM),以便你可以在以后重构你的数据存储结构。

还有很多你可以使用的其他想法。 网上有很多很棒的博客,像highscalabilty.org一样,并确保你了解CAP定理。

还要考虑一个caching层,比如Redis或者memcache。 我将把这些产品之一放在我的数据层前面。 当我查询mongo(正在存储所有规范化的东西)时,我使用这些数据来构造一个扁平的表示并将其存储在caching中。 当我更新数据时,我将使caching中引用我正在更新的任何数据无效。 (尽pipe您必须花费时间来使caching中的数据和跟踪数据无效,并将数据更新为考虑您的缩放因子)。 有人曾经说过:“计算机科学中最困难的两件事是命名和caching失效。”

希望有所帮助!

尝试将UserEvent属性的IList添加到您的User对象。 您没有详细说明您的域模型是如何devise的。 有关示例,请查看NoRM组http://groups.google.com/group/norm-mongodb/topics

在1Schema.com ,我们正试图帮助解决这个问题!

我们的目标是帮助您devise您的NoSQL数据库,以便每个页面请求可以在单个读取操作中获取其数据。

为此,我们区分“实际数据”(实际上存在于文档中)和“caching数据”(存在于文档之外,但本地复制)

更新文档中的“实际数据”会导致其所有高速caching副本自动更新

相反,您不应该更新文档中的“caching数据”,因为我们的更改传播代码会自动更新这些数据

为此,我们使用不同types的边来表示不同的行为:

“亲子”边确定存在与同一根文档相关联的数据,产生一个嵌套的子文档数组(“领域驱动devise”中的“聚合模式”)

“外键”边缘决定了其他文档如何根据ID参考(DDD中的交叉聚合引用)在给定文档中本地高速caching

我们使用模式来自动化源文档更改时如何更新caching数据,而不是使用模式来强制实施约束

请检查我们的导出到MongoDB,看看我们如何自动变化传播…所有导出的代码运行在Mongo shell中,不需要特殊的库