mongo设计(二)
原文:http://blog.mongodb.org/post/87892923503/6-rules-of-thumb-for-mongodb-schema-design-part-2
By William Zola, Lead Technical Support Engineer at MongoDB
在上一篇文章中我介绍了三种基本的设计方案:内嵌,子引用,父引用,同时说明了在选择方案时需要考虑的两个关键因素。
一对多中的多是否需要一个单独的实体。
这个关系中集合的规模是一对很少,很多,还是非常多。
在掌握了以上基础技术后,我将会介绍更为高级的主题:双向关联和反范式化。
双向关联
如果你想让你的设计更酷,你可以让引用的“one”端和“many”端同时保存对方的引用。
以上一篇文章讨论过的任务跟踪系统为例。有person和task两个集合,one-to-n的关系是从person端到task端。在需要获取person所有的task这个场景下需要在person这个对象中保存有task的id数组,如下面代码所示。

在某些场景中这个应用需要显示任务的列表(例如显示一个多人协作项目中所有的任务),为了能够快速的获取某个用户负责的项目可以在task对象中嵌入附加的person引用关系。

这个方案具有所有的一对多方案的优缺点,但是通过添加附加的引用关系。在task文档对象中添加额外的“owner”引用可以很快的找到某个task的所有者,但是如果想将一个task分配给其他person就需要更新引用中的person和task这两个对象(熟悉关系数据库的童鞋会发现这样就没法保证操作的原子性。当然,这对任务跟踪系统来说并没有什么问题,但是你必须考虑你的用例是否能够容忍)
在一对多关系中应用反范式
在你的设计中加入反范式,可以使你避免应用层级别的join读取,当然,代价是这也会让你在更新是需要操作更多数据。下面我会举个例子来进行说明
反范式Many -< One
以产品和零件为例,你可以在parts数组中冗余存储零件的名字。以下是没有加入反范式设计的结构。

反范式化意味着你不需要执行一个应用层级别的join去显示一个产品所有的零件名字,当然如果你同时还需要其他零件信息那这个应用层的join是避免不了的。

在使得获取零件名字简单的同时,执行一个应用层级别的join会和之前的代码有些区别,具体如下:

反范式化在节省你读的代价的同时会带来更新的代价:如果你将零件的名字冗余到产品的文档对象中,那么你想更改某个零件的名字你就必须同时更新所有包含这个零件的产品对象。
在一个读比写频率高的多的系统里,反范式是有使用的意义的。如果你很经常的需要高效的读取冗余的数据,但是几乎不去变更他d话,那么付出更新上的代价还是值得的。更新的频率越高,这种设计方案的带来的好处越少。
例如:假设零件的名字变化的频率很低,但是零件的库存变化很频繁,那么你可以冗余零件的名字到产品对象中,但是别冗余零件的库存。
需要注意的是,一旦你冗余了一个字段,那么对于这个字段的更新将不在是原子的。和上面双向引用的例子一样,如果你在零件对象中更新了零件的名字,那么更新产品对象中保存的名字字段前将会存在短时间的不一致。
反范式One -< Many
你也可以冗余one端的数据到many端:

如果你冗余产品的名字到零件表中,那么一旦更新产品的名字就必须更新所有和这个产品有关的零件,这比起只更新一个产品对象来说代价明显更大。这种情况下,更应该慎重的考虑读写频率。
在一对很多的关系中应用反范式
在日志系统这个一对许多的例子中也可以应用反范式化的技术。你可以将one端(主机对象)冗余到日志对象中,或者反之。
下面的例子将主机中的IP地址冗余到日志对象中。

如果想获取最近某个ip地址的日志信息就变的很简单,只需要一条语句而不是之前的两条就能完成。

事实上,如果one端只有少量的信息存储,你甚至可以全部冗余存储到多端上,合并两个对象。

另一方面,也可以冗余数据到one端。比如说你想在主机文档中保存最近的1000条日志,可以使用mongodb 2.4中新加入的$eache/$slice功能来保证list有序而且只保存1000条。
日志对象保存在logmsg集合中,同时冗余到hosts对象中。这样即使hosts对象中超过1000条的数据也不会导致日志对象丢失。

通过在查询中使用投影参数 (类似{_id:1})的方式在不需要使用logmsgs数组的情况下避免获取整个mongodb对象,1000个日志信息带来的网络开销是很大的。
在一对多的情况下,需要慎重的考虑读和更新的频率。冗余日志信息到主机文档对象中只有在日志对象几乎不会发生更新的情况下才是个好的决定。
总结
在这篇文章里,我介绍了对三种基础方案:内嵌文档,子引用,父引用的补充选择。
使用双向引用来优化你的数据库架构,前提是你能接受无法原子更新的代价。
可以在引用关系中冗余数据到one端或者N端。
在决定是否采用反范式化时需要考虑下面的因素:
你将无法对冗余的数据进行原子更新。
只有读写比较高的情况下才应该采取反范式化的设计。
下次,我将会告诉你在面对这些方案时该如何抉择。
mongo设计(二)的更多相关文章
- JavaScript 框架设计(二)
JavaScript 高级框架设计 (二) 上一篇,JavaScript高级框架设计(一)我们 实现了对tag标签的选择 下来我们实现对id的选择,即id选择器. 我们将上一篇的get命名为getTa ...
- 游戏UI框架设计(二) : 最简版本设计
游戏UI框架设计(二) --最简版本设计 为降低难度决定先讲解一个最简版本,阐述UI框架的核心设计理念.这里先定义三个核心功能: 1:UI窗体的自动加载功能. 2:缓存UI窗体. 3:窗体生命周期(状 ...
- Redis缓存项目应用架构设计二
一.概述 由于架构设计一里面如果多平台公用相同Key的缓存更改配置后需要多平台上传最新的缓存配置文件来更新,比较麻烦,更新了架构设计二实现了缓存配置的集中管理,不过这样有有了过于中心化的问题,后续在看 ...
- Java秒杀简单设计二:数据库表和Dao层设计
Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表 https://www.cnblogs.com/taiguyiba/p/9791431.html ...
- ASP.NET MVC +EasyUI 权限设计(二)环境搭建
请注明转载地址:http://www.cnblogs.com/arhat 今天突然发现博客园出问题了,老魏使用了PC,手机,平板都访问博客园了,都是不能正常的访问,原因是不能加载CSS,也就是不能访问 ...
- APP和服务端-架构设计(二)
1. App架构设计经验谈:接口的设计 App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 1.1 安全机制的设计 现在,大部分App的接口 ...
- WDA演练一:用户登陆界面设计(二)
一,登陆界面设计: 1.将系统编号灰显,默认初值 2.密码栏勾选密码显示,这样就不会明文显示在页面上了: Init方法中添加默认值代码: METHOD wddoinit . DATA lo_nd_zh ...
- GPS部标平台的架构设计(二) 可扩展性设计
在设计的前夕,设计人员喜欢把领导对未来业务的期望带入到设计目标当中,比如当前业务也不过是接入几千辆车,未来业务增长也不过几万台,但领导很多激情,强势要求二期平台的接入能力要达到20万台,这个要求带入到 ...
- bootstrap学习总结-css样式设计(二)
首先,很感谢各位园友对我的支持,关于bootstrap的学习总结,我会持续更新,如果有写的不对的地方,麻烦各位给我指正出来哈.关于上篇文章,固定布局和流式布局很关键,如果还不太清楚的可以再看看我写的h ...
随机推荐
- http协议说明
今天公司有同事让我给他讲一讲http..然后自己写了一个示例代码,这如果都看不懂.那我也没办法了.... <?php //这里服务器以apache举例.nginx.iis.他们实际上处理方式的都 ...
- printf--动态指定输出格式长度
char a1[] = {'A', 'B', 'C'}; char a2[] = "world"; printf(, a1, , a2); printf("[%.*s][ ...
- FTP配置参数
格式 vsftpd.conf 的格式非常简单,每行要么是一个注释,要么是一个指令.注释行以#开始并被忽略掉.指令行格式如下: 配置项=参数值 很重要的一点是,这个格式里不存在任何空格. 默认的,每一个 ...
- KVO的实现原理探寻
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- 测试框架mochajs详解
测试框架mochajs详解 章节目录 关于单元测试的想法 mocha单元测试框架简介 安装mocha 一个简单的例子 mocha支持的断言模块 同步代码测试 异步代码测试 promise代码测试 不建 ...
- PHP中的错误处理
程序只要在运行,就免不了会出现错误!或早或晚,只是时间问题罢了. 错误很常见,比如Notice,Warning等等.此时一般使用set_error_handler来处理: <?php set_e ...
- wikioi1688 求逆序对
题目描述 Description 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目 数据范围:N<=105.Ai<=105. ...
- Windows去掉桌面SVN文件或文件夹问号
将版本库 的内容检出 到桌面,后才发现桌面上的文件 都变成了问号,本来也以为没有多大问题,删除 .svn 即可,可是删除所有的.svn后,桌面上还是显示问号,刷新了很多次,还重启电脑 了,问号也没有消 ...
- git 之别名配置
在git操作中有很多命令我们自己可以起别名,以提高操作效率. 1. 配置方式 1)项目级别的配置,仅对当前项目生效(将写入到.git/config文件中) $ git config --glob ...
- hibou 主界面自己侧滑的定义
要打滑View参加UIPanGestureRecognizer #pragma mark 手势识别器回调方法 - (void)dragView:(UIPanGestureRecognizer *)ge ...