我知道,以“非规范化方式”或“nosql 方式”思考。
但是告诉我这个简单的用例。
db.users
db.comments
一些用户发表评论,我想在获取评论时获取一些用户数据。假设我想显示动态数据,如“用户级别”,以及静态数据,如“用户名”。
使用静态数据我永远不会有问题,但是动态数据呢?
用户级别在用户整理中,我需要将非规范化数据复制到评论中以实现读取性能,同时还要更新用户级别。
这可以以某种方式存档吗?
我知道,以“非规范化方式”或“nosql 方式”思考。
但是告诉我这个简单的用例。
db.users
db.comments
一些用户发表评论,我想在获取评论时获取一些用户数据。假设我想显示动态数据,如“用户级别”,以及静态数据,如“用户名”。
使用静态数据我永远不会有问题,但是动态数据呢?
用户级别在用户整理中,我需要将非规范化数据复制到评论中以实现读取性能,同时还要更新用户级别。
这可以以某种方式存档吗?
刚刚找到了来自 10gen 的 Brendan McAdams 的答案,他显然比我更有权威,他建议嵌入文档。
第一个是手动将他们所属的用户的每个评论 ObjectID 包括在内。
comment: { text : "...",
date: "...",
user: ObjectId("4b866f08234ae01d21d89604"),
votes: 7 }
第二种,聪明的方法是使用 DBRefs
我们向磁盘添加了额外的 I/O,这会降低性能,对吗?(我不确定这在内部是如何工作的)因此我们需要尽可能避免链接,对吧?
是的 - 还会有一个查询,但驱动程序会为您完成 - 您可以将其视为一种语法糖。会影响性能吗?实际上,这也取决于:) Mongo 如此快速的原因之一是它使用内存映射文件
,并且 mongo 尽量将所有工作集(加上索引)直接保存在 RAM 中。并且每 60 秒(默认情况下)它会将 RAM 快照与基于磁盘的文件同步。
当我说工作集时,我的意思是你正在使用的东西:你可以拥有三个集合 - foo、bar、baz,但是如果你现在只使用 foo 和 bar,它们应该被加载到 ram 中,而 baz 留在磁盘上被遗弃。此外,内存映射文件只允许加载集合的一部分。因此,如果您正在构建诸如 engadget 或 techcrunch 之类的东西,那么工作集很可能是过去几天的评论,而旧页面的恢复频率会降低(评论会按需生成到内存中),所以它不会t 显着影响性能。
所以回顾一下:只要你在内存中保持工作集(你可能认为这是读/写缓存),获取这些东西是超快的,再一次查询就不会成为问题。如果您使用不适合内存的数据切片,则会出现速度下降,但我现在不知道您的情况——这可能是可以接受的,所以在这两种情况下,我都倾向于选择使用链接。