我是新手NOSQL的新手,最近对mongoDB很感兴趣.我正在从头开始创建一个新网站,并决定使用MONGODB/NORM(用于C#)作为我唯一的数据库.我一直在阅读很多关于如何正确设计文档模型数据库的内容,我认为在很大程度上我的设计运行得非常好.我大约6个月进入我的新网站,我开始看到我需要一遍又一遍地处理数据复制/同步的问题.从我读到的内容来看,这在文档模型中是可以预期的,并且对于性能而言是有意义的.IE将嵌入的对象粘贴到文档中,因此读取速度快 - 没有连接; 但是当然你不能总是嵌入,所以mongodb有这个DbReference的概念,它基本上类似于关系数据库中的外键.
所以这是一个例子:我有用户和事件; 两者都获得自己的文件,用户参加活动,活动有用户参加.我决定将有限数据的事件列表嵌入到User对象中.我还将用户列表嵌入到Event对象中作为"与会者".现在的问题是我必须使用户与同样嵌入在Event对象中的用户列表保持同步.正如我所读到的,这似乎是首选的方法,也是NOSQL做事的方式.检索很快,但回退是当我更新主用户文档时,我还需要进入Event对象,可能找到对该用户的所有引用并更新它.
所以我的问题是,这是人们需要处理的一个非常普遍的问题吗?在你开始说"可能NOSQL策略不适合我在这里尝试做的事情"之前,这个问题要发生多少?什么时候不必加入连接的性能优势变成了一个缺点,因为你很难在嵌入式对象中保持数据同步并对数据库执行多次读取操作?
那就是与文档商店的权衡.您可以像任何标准RDMS一样以标准化方式存储,并且您应该尽可能地争取规范化.只有在性能受到影响的情况下才能打破规范化并使数据结构变得扁平化.权衡取决于读取效率与更新成本.
Mongo具有非常高效的索引,可以像传统的RDMS一样使规范化变得更容易(大多数文档存储不会免费提供这个,这就是为什么Mongo更像是混合而不是纯文档存储).使用此功能,您可以在用户和事件之间进行关系收集.它类似于表格数据存储中的代理表.索引事件和用户字段,它应该非常快,可以帮助您更好地规范化数据.
我喜欢绘制平面结构的效率与保持标准化的效率,当我需要更新记录数据与读出查询中需要的内容时.你可以用大O表示法来做,但你不必那么花哨.只需根据一些具有不同数据模型的用例将一些数字放在纸上,并获得有关需要多少工作的良好直觉.
基本上我所做的是首先尝试预测记录将有多少次更新的概率与它读取的频率.然后我尝试预测更新的成本与读取的比例,当它被标准化或扁平化时(或者可能是两部分的组合,我可以设想...许多优化选项).然后,我可以判断保持平稳的成本与从标准化来源建立数据的成本.一旦我绘制了所有变量,如果保持平衡的节省使我节省了一大堆,那么我将保持平坦.
一些提示:
如果你需要快速和原子的快速查找(完全是最新的),你可能需要一个有利于解决方案,你喜欢扁平化而不是规范化并对更新进行点击.
如果您需要快速更新,并立即访问,则支持规范化.
如果您需要快速查找但不需要完美的最新数据,请考虑在批处理作业中构建规范化数据(可能使用map/reduce).
如果您的查询需要快速,并且更新很少,并且不一定要求您的更新可以立即访问,或者需要事务级别锁定它已经100%的时间(为了保证您的更新写入磁盘),可以考虑将更新写入队列,在后台处理它们.(在此模型中,您可能必须稍后处理冲突解决和协调).
配置不同型号.在代码中构建数据查询抽象层(如某种方式中的ORM),以便以后可以重构数据存储结构.
您可以使用许多其他想法.网上有很多很棒的博客,比如highscalabilty.org,并确保你理解CAP定理.
还要考虑一个缓存层,如Redis或memcache.我将其中一个产品放在我的数据层前面.当我查询mongo(存储所有规范化的内容)时,我使用数据构造一个展平的表示并将其存储在缓存中.当我更新数据时,我将使缓存中引用我正在更新的内容的任何数据无效.(尽管您必须花费时间使数据无效并跟踪缓存中的数据,并将其更新为考虑您的缩放因子).曾经有人曾说过"计算机科学中最难的两件事就是命名和缓存失效."
希望有所帮助!