【问题标题】:To embed or not embed?嵌入还是不嵌入?
【发布时间】:2013-04-15 13:56:52
【问题描述】:

我正在尝试找出我应该使用哪种架构设计。

(这些是示例文档,实际文档包含更多属性)

嵌入式:

{
   _id: ObjectId(),
   title: "trolo",
   subs: [
      {
         owner: refUserId
      },
      ...
   ]
}

我的索引:ensureIndex({ "subs.owner": 1 })

标准化:

Collection A:
{
   _id: ObjectId(),
   title: "trolo"
}
Collection B:
{
   parent: refId,
   owner: refUserId
}

我的索引:ensureIndex({ owner: 1 })

我在不同型号上运行了一些benchRun() 测试。但结果非常令人惊讶。

嵌入式查询:

ops = [
    {op: "find", ns: t.getFullName(), query: { "subs.owner": someUserId }}
]

规范化查询:

ops = [
    {op: "find", ns: t.getFullName(), query: { owner: someUserId }}
]

benchRun 脚本:

for (x = 1; x <= 128; x *= 2) {
    res = benchRun({
        parallel : x,
        seconds : 5,
        ops : ops
    });
    print( "threads: " + x + "\t queries/sec: " + res.query);
}

输出:

嵌入式:

threads: 1       queries/sec: 11331
threads: 2       queries/sec: 16764.6
threads: 4       queries/sec: 21587
threads: 8       queries/sec: 25198.6
threads: 16      queries/sec: 24717.6
threads: 32      queries/sec: 24707.4
threads: 64      queries/sec: 25813.8
threads: 128     queries/sec: 30785.4

标准化:

threads: 1       queries/sec: 8.4
threads: 2       queries/sec: 13.2
threads: 4       queries/sec: 16.4
threads: 8       queries/sec: 17.4
threads: 16      queries/sec: 18.2
threads: 32      queries/sec: 20.8
threads: 64      queries/sec: 27.4
threads: 128     queries/sec: 39.6

为什么归一化模型这么慢?我本来希望它是最快的。

更新

这是.explain() 对我的查询的看法。

嵌入式

> db.embedded.find({"subs.owner":ObjectId("516ea63322f2a93c4fef8542")}).explain()

{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 5,
        "nscannedObjects" : 5,
        "nscanned" : 5,
        "nscannedObjectsAllPlans" : 5,
        "nscannedAllPlans" : 5,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {

        },
        "server" : "localhost:27017"
}

标准化

> db.collectionB.find({owner: ObjectId("516ea63322f2a93c4fef8542")}).explain()
{
        "cursor" : "BtreeCursor owner_1",
        "isMultiKey" : false,
        "n" : 76625,
        "nscannedObjects" : 76625,
        "nscanned" : 76625,
        "nscannedObjectsAllPlans" : 76625,
        "nscannedAllPlans" : 76625,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 91,
        "indexBounds" : {
                "owner" : [
                        [
                                ObjectId("516ea63322f2a93c4fef8542"),
                                ObjectId("516ea63322f2a93c4fef8542")
                        ]
                ]
        },
        "server" : "localhost:27017"
}

【问题讨论】:

  • 您是否尝试在查询中使用explain 来查看发生了什么?
  • 这就是我现在正在做的事情:),不知道为什么我之前没有想到它。但我的规范化查询有indexOnly:false,所以我正在阅读docs.mongodb.org/manual/tutorial/…
  • 其他人最近注意到indexOnly:false 可能非常令人困惑并且难以explain [叹气] :) .
  • 它在“标准化”的情况下扫描 76000+ 个文档?唔。这似乎根本不对。
  • 76625 是文档数,我相信。但是现在你提到它似乎有点高,需要检查我的构建脚本:)。无论如何,由于它使用所有者索引,因此不需要扫描整个集合吧?

标签: mongodb schema normalization denormalization


【解决方案1】:

为什么您希望规范化更快?通过嵌入,文档存储在磁盘上的单个位置。通过一次磁盘查找,可以恢复整个文档。如果它被规范化,它会分布在磁盘上,这意味着 2 个磁盘寻求获取信息。根据磁盘的速度和针必须去的扇区,它不可避免地会比嵌入式文档模型慢。

【讨论】:

  • 因为它必须搜索嵌套文档。我注意到,在执行 $unwind 和 $match 后,嵌入式模型的性能下降到 0 次查询/秒。
  • 否,因为 bsonspec 允许跳过嵌套的子文档
猜你喜欢
  • 2011-01-23
  • 2019-05-16
  • 1970-01-01
  • 2011-02-09
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 2015-07-20
相关资源
最近更新 更多