更新Mongodb中的嵌入式文档:性能问题?

网络

我是Mongodb的新手,听说Mongodb非常适合进行大量的读写操作。嵌入式文档是实现它的功能之一。但是我不确定这是否也是性能问题的原因。图书文件示例:

{
    "_id": 1,
    "Authors": [
        {
            "Email": "email",
            "Name": "name"
        }
    ],
    "Title": "title",
    ...
}

如果一位作者有成千上万的书,并且他的电子邮件需要更新,我需要写一些查询

  1. 搜索所有书籍文档,并与该作者挑选出数千本书
  2. 在这些书籍文档中更新作者的电子邮件字段

这些操作似乎效率不高。但是这种更新无处不在,我相信开发人员已经考虑了这一点。那么,我在哪里弄错了?

克列丹

您当前的嵌入式架构设计有其优点,其中之一就是数据局部性。由于MongoDB将数据连续存储在磁盘上,因此将所需的所有数据都放在一个文档中可确保旋转的磁盘将花费更少的时间查找磁盘上的特定位置。

如果您的应用程序经常访问books信息和Authors数据,那么您几乎肯定会想走嵌入式路线。嵌入式文档的另一个优点是写入数据时的原子性和隔离性。

为了说明这一点,假设您要更新一位作者的所有书籍的电子邮件字段,可以通过一个(原子)操作来完成,这不是MongoDB的性能问题:

db.books.updateMany(
    { "Authors.name": "foo" },
    {
        "$set": { "Authors.$.email": "[email protected]" }
    }
);

或更早的MongoDB版本:

db.books.update(
    { "Authors.name": "foo" },
    {
        "$set": { "Authors.$.email": "[email protected]" }
    },
    { "multi": true }
)

在上面的代码中,您使用了位置$运算符,它通过标识要更新的数组中的元素而无需显式指定该元素在数组中的位置,从而方便了对包含嵌入式文档的数组的更新。将其与运算符上的点符号一起使用$

有关MongoDB中数据建模的更多详细信息,请阅读docs数据建模简介,特别是与嵌入式文档建立一对多关系


您可以考虑的另一个设计选项是引用遵循规范化架构的文档。例如:

// db.books schema
{
    "_id": 3
    "authors": [1, 2, 3] // <-- array of references to the author collection
    "title": "foo"
}

// db.authors schema
/*
1
*/
{
    "_id": 1,    
    "name": "foo",
    "surname": "bar",
    "address": "xxx",
    "email": "[email protected]"
}
/*
2
*/
{
    "_id": 2,    
    "name": "abc",
    "surname": "def",
    "address": "xyz",
    "email": "[email protected]"
}
/*
3
*/
{
    "_id": 3,    
    "name": "alice",
    "surname": "bob",
    "address": "xyz",
    "email": "[email protected]"
}

当您具有非常不可预测的一对多关系时,上述使用文档引用方法的规范化架构也具有优势。如果每个给书实体有成百上千的作者文档,那么就空间限制而言,嵌入会有很多挫折,因为文档越大,它使用的RAM越多,而MongoDB文档的硬大小限制为16MB。

对于查询规范化模式,可以考虑使用聚合框架的$lookup运算符,该运算符authors对同一数据库中集合执行左外部联接,以从集合中过滤文档以books进行处理。


因此,我认为您的当前模式比创建单独的集合更好,authors因为单独的集合需要更多的工作,即查找一本书及其作者是两个查询,并且需要额外的工作,而上述模式嵌入的文档既简单又快速(单个寻求)。插入和更新没有太大差异。因此,如果您需要选择单个文档,需要对查询进行更多控制或拥有庞大的文档,则单独的集合是不错的选择。当你想整个文档,用文档嵌入文档都还不错$slice的嵌入式的authors,或没有authors在所有。

一般的经验法则是,如果您的应用程序的查询模式是众所周知的,并且倾向于仅以一种方式访问​​数据,则嵌入式方法会很好地工作。如果您的应用程序以多种方式查询数据,或者您无法预期数据查询模式,则更规范的文档引用模型将适合这种情况。

参考:

MongoDB应用设计模式:领先的NoSQL数据库的实际用例作者:Rick Copeland

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TOP 榜单

热门标签

归档