MongoDB性能:newsfeed架构,订阅者,评论


MongoDB performance: newsfeed architecture, subscribers, comments

我使用MongoDB+PHP作为一个"facebookish"新闻提要,包含不同类型的提要(帖子、照片、民意调查等)和评论。

每个提要都属于某个"通道"-目前可能是用户(未来可能会有更多容器)。

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

现在让我们假设有大量的频道和大量的提要。频道/订阅源/评论的最佳结构是什么?

我正在考虑两种方法:

1)订阅源集合,每个订阅源中都有订阅者列表:

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

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

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

如果我想获得带有新评论的提要:

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

优点:

  • 简单快速的读数

缺点:

  • 当我想订阅/取消订阅频道时,我必须运行浏览所有订阅源并从列表中推/拉我的名字channel_subscribers;如果我有大量的饲料,可能会很慢

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"})

优点:

  • 简单、快速、更安全的订阅/取消订阅

缺点:

  • 我觉得我应该避免中的$,因为它很慢(?),尤其是当我有很多订阅了放置在此运算符内部

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

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

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

4)你的建议

好的,我自己回答。我试着在我的笔记本电脑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的文档中创建如此大的多关键字字段绝对不是一个好主意。