我应该如何构建MongoDB的数据模式?

时间:2011-07-11 07:48:28

标签: mongodb schema

我有一个聊天室系统,我想使用MongoDB作为后端数据库。以下是实体:

  • 房间 - 聊天室(room_id)
  • 用户 - 聊天室中的聊天用户(room_id,user_name)
  • 消息 - 聊天室中的消息(room_id,user_name,message)

为了设计架构,我有一些想法:首先,3个集合 - 房间,用户和消息 - 在用户和消息文档中有一个父引用。

另一个想法是为每个房间创建集合。如

  • db.chatroom.victor
    • db.chatroom.victor.users
    • db.chatroom.victor.msgs
  • db.chatroom.john
    • db.chatroom.john.users
    • db.chatroom.john.msgs
  • db.chatroom.tom
    • db.chatroom.tom.users
    • db.chatroom.tom.msgs

...

我认为如果我可以将文档划分为不同的集合,那么查询会更有效。此外,我可以使用上限集合来限制每个房间中的消息数量。但是,我不熟悉MongoDB。我不确定这样做是否有任何副作用,或者是否存在创建大量集合的性能问题?是否有设计MongoDB架构的指南?

感谢。

3 个答案:

答案 0 :(得分:5)

你应该总是通过回答2个问题来设计你的架构:

  • 我应该存储哪些数据? (临时/永久地)
  • 我将如何访问该数据? (很多关于此的内容,很多关于此的内容,随机的rw)

您不希望将高访问率数据嵌入到文档中(例如每隔一秒左右由每个用户访问的聊天消息),最好将其作为单独的集合。

另一方面,

- 聊天室中用户的收集变化很少 - 你绝对可以嵌入。

只是使用常识进行设计,你会没事的

答案 1 :(得分:1)

您绝对不希望在其他文档中嵌入邮件。他们需要作为单独的文档存储。

我这样说是因为MongoDB为它写的每个文件分配了一定的空间。当它写入文档时,它会获取当前大小并为文档添加一些空白空间(填充),这样如果它实际上是1k大,则可能会变大1.5k,从而为文档的大小增加空间。

聊天消息几乎肯定每个都大于分配的可用空间。多条消息绝对会大于可用空间。

问题是,当您尝试在其中嵌入另一个文档(通过更新)时,文档在磁盘\内存中的当前位置不适合时,数据库必须从磁盘\内存中读取该文档并重写整个文档数据文件尾部的东西。

这导致很多磁盘活动本来应该不存在 - 添加的I / O会破坏数据库的性能。

答案 2 :(得分:0)

考虑所有用例。你想要执行什么样的查询?

  • “告诉我用户正在聊天的房间”。这不适用于当前架构,您必须向用户或单独的集合中添加房间列表以使其工作。
  • “显示用户在所有房间发送的所有消息”。这再次无效。
  • “删除所有房间中的所有空闲用户”。使用建议的模式,您必须在每个room.users集合上运行此查询。

另外,对集合的大小做一些近似。如果您有100个房间,最多1000个用户,那么对于存储所有这些映射的集合,这是100000个条目。如果房间和用户的索引不应成为问题,则不需要单独的集合。

有100个用户,您甚至可以将其作为数组嵌入到房间对象中。只要确保有索引。