【问题标题】:MongoDB performance: newsfeed architecture, subscribers, commentsMongoDB 性能:新闻提要架构、订阅者、评论
【发布时间】:2012-01-28 09:32:07
【问题描述】:

我将 MongoDB + PHP 用于具有不同类型的提要(帖子、照片、投票等)和 cmets 的“facebookish”新闻提要。

每个供稿都属于某个“频道” - 当前可能是 usergroup(将来可能会有更多容器)。

任何用户都可以订阅或取消订阅任何频道。

现在假设有大量的频道和大量的提要。通道/feeds/cmets 的最佳结构是什么?

我正在考虑两种方法:

1) Feed 集合,其中包含每个 Feed 中的订阅者列表:

feeds: 
[
   {date_added: ..., 
    last_update: ..., 
    title: ...,
    text: ...,
    channel: ..., 
    channel_subscribers: [...],
    comments_subscribers: [...],
    comments: [...] 

   },
   {...},
   {...},
   {...}
]

如果我想获得最后的提要:

db.feeds.find({date_added: "this week", channel_subscribers: "my_login"});

如果我想获得新 cmets 的供稿:

db.feeds.find({last_update: "this week", comments_subscribers: "my_login"});

优点:

  • 简单快速的读数?

缺点:

  • 当我想订阅/取消订阅频道/取消订阅频道时,我必须运行 通过所有提要并从列表中推/拉我的名字 频道订阅者;如果我有大量的提要,它可能会很慢

2) 单独的“渠道”集合: 同样的事情,但在频道集合中保留订阅者列表:

channels: 
[
  {channel_id:..., last_update: ..., subscribers: [...]},
  {channel_id:..., last_update: ..., subscribers: [...]}
]

首先我要查询最后更新的频道:

subscribes = db.channels.find({last_update: "today", subscribers: "my_login"})

现在找到我的供稿:

db.feeds.find({channel: {$in: subscribes}], date_added: "today"})

优点:

  • 订阅/退订简单、快速、安全;

缺点:

  • 我觉得我应该避免使用 $in,因为它很慢(?),尤其是当我有很多 订阅放在这个操作符里面。

3) 将用户订阅保存在 users 集合中(因此每个用户都有自己的订阅数组)

users:
[
  {_id: ..., login: ..., email: ..., subscribes: [...]}
]

缺点: - 在这种情况下,我们将在 $in 中放入比之前(#2)方法更大的数组。

4) 您的建议?

【问题讨论】:

  • MongoDB 建议您使用的数据结构适合您最常见的用例。不过,理解您当前的结构仍然有些困难。你能详细说明一下你的结构吗?
  • 好的,让我简化一下我的问题。什么会更快:保留我的订阅列表,然后将那个大数组放在“$in”运算符中,然后通过它获取我的提要;或者 - 通过我的登录名获取订阅源 - 当每个订阅源中都有大量(约 2000 个)订阅者时? (在这么大的数组上创建多键索引是一种好习惯吗?)
  • 我认为将订阅者保留在订阅源本身是个坏主意。将它们链接起来可能会更好。这看起来有点 SQLey,但它也便于搜索和删除。
  • 谢谢!我想我最好对这两种情况进行速度测试并在此处发布结果。

标签: php performance mongodb feed


【解决方案1】:

好的,我自己来回答。我试图在我的笔记本电脑 Windows 7 32 位/2GB RAM 上进行测试。 我创建了一个“提要”集合并用 500 个提要填充它:

feeds:
[
 {_id: ..., subscribers: [...]},
 {_id: ..., subscribers: [...]},
]

每个“订阅者”数组都有一个包含 2000 个短随机字符串名称的列表。

首先我必须提到我的数据库的大小从 60Mb 增加到 1.5Gb。

然后当我运行 shell 命令db.feeds.ensureIndex({subscribers: 1}) 时,它会挂起约 3 分钟,然后停止并出现错误:"can't map file memory - mongo requires 64 bit build for larger datasets"

因此,在 mongo 的文档中创建如此大的多键字段绝对不是一个好主意。

【讨论】:

  • 请注意,32 位 mongo 版本有一个 hard limit of 2GB for the data 。但无论如何,将它分开绝对是有意义的,这样引用会更快、更容易。因为您希望链接到用户对象而不仅仅是字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多