基本数据模型由3个对象组成:
A: ObjectId id, String name, List of B objects
B: ObjectId id, String name
C: ObjectId id, reference to B object
类型为A
和B
的对象很少会被创建(可能每月都有一个这样的对象)。每个A
对象只包含几个(= 1-5)B
个对象。如果我使用嵌入,它将如下所示:
{
id : ObjectId(...),
name : "some A name",
bList : [
{
id : ObjectId(...),
name : "some B name"
},{
id : ObjectId(...),
name : "some other B name"
}
]
}
C类型的对象总是这样:
{
id : ObjectId(...),
bReference : ObjectId(...)
}
我无法将C嵌入到B中,因为可能存在无限(=数百万个条目连接到单个B对象)的C对象数。
A和B对象可能每月修改一次。 C对象将从不进行修改。但是C对象将经常插入(峰值负载应该是每秒约20次插入)。
每当我查询类型为C的文档时,我都需要来自引用的B文档的一些信息(有时还需要来自A文档)。例如,如果允许我访问C对象,我需要检查:
c = db.c.find({ ... })
a = db.a.find({ bList.id : c.bReference })
// do something with the access permission information from within a.
如果我需要来自A和B的信息,这似乎很不错。正确?
但是,如果我只需要来自B档案的信息(通常情况下),该怎么办?
c = db.c.find({ ... })
b = db.a.find({ bList.id : c.bReference }, { bList.$ : 1 })
如果我查询多个C对象,它们将始终(!)引用相同的B对象。使用非嵌入式数据库设计时,查询将如下所示:
c = db.c.find({ ... })
b = db.b.find({ _id : c.bReference })
最重要的问题是:如果我经常这样做,这两种变体会有很大的性能差异吗?
奖金问题:
我可以在所有A对象中使用唯一约束吗?我想让所有那些a.bList.id ObjectIds都是唯一的(我知道它们应该(!)是全局唯一的,但是对数据库级别有约束让我觉得更安全)
答案 0 :(得分:0)
你的第一个问题的答案通常是:它取决于你。如果对象很大(比如每个数百k),可能会有轻微的性能损失。如果对象相对较小,则应该没有太大差异。
当然,'轻微','大','小'等都非常模糊,所以让我详细说明:因为A
和B
对象非常少而且它们是经常查询,它们可能会保留在RAM中这是好的,因此唯一的潜在瓶颈是串行器/解串器和网络。但是,假设您每秒进行1000次查询,对象的大小为1k,那么这是1MB / s - 仍然不是特别高的负载。
如果对象的大小为100k,我们会谈论100MB / s或大约1Gbit / s,这是一个完全不同的游戏 - 对于功能强大的服务器来说肯定不是很高的负载,但它可能会扼杀20美元/ m虚拟专用服务器。然后,即使按照这种速率,您可能希望将这些对象缓存一两秒,从而大大减少读取的网络负载。
简而言之,每秒20次操作,不用担心。
从这里我可以看到其他答案,我经常建议不要嵌入,但由于很少修改数据,嵌入应该没问题。