9

我一直在研究 MongoDB 上的数组(多键)索引,并且我有以下问题,我无法找到很多文档:

子文档数组上的索引

因此,如果我有一个看起来像这样的数组字段:

{field : [
  {a : "1"}, 
  {b : "2"}, 
  {c : "3"}
  ]
}

我只是单独查询(不是一起查询) field.afield.c我相信我可以在以下选项之间进行选择:

  1. db.Collection.ensureIndex({field : 1});
  2. db.Collection.ensureIndex({field.a : 1}); db.Collection.ensureIndex({field.c : 1});

即:对整个数组的索引;或嵌入字段上的两个索引。现在我的问题是:

  • 您如何在选项 1 中可视化整个数组的索引(它甚至有用)?这样的索引对哪些查询有用?
  • 鉴于我描述的查询情况,以上两个选项哪个更好,为什么?
4

1 回答 1

8

您是正确的,如果您只查询字段数组中的 a 的值,那么从某种意义上说,这两个索引都会帮助您提高查询的性能。

但是,请查看以下 3 个查询:

> db.zaid.save({field : [{a: 1}, {b: 2}, {c: 3}] });
> db.zaid.ensureIndex({field:1});
> db.zaid.ensureIndex({"field.a":1});

#Query 1
> db.zaid.find({"field.a":1})
{ "_id" : ObjectId("50b4be3403634cff61158dd0"), "field" : [ { "a" : 1 }, { "b" : 2 }, { "c" : 3 } ] }
> db.zaid.find({"field.a":1}).explain();
{
    "cursor" : "BtreeCursor field.a_1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "field.a" : [
            [
                1,
                1
            ]
        ]
    }
}

#Query 2
> db.zaid.find({"field.b":1}).explain();
{
    "cursor" : "BasicCursor",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

    }
}

#Query 3
> db.zaid.find({"field":{b:1}}).explain();
{
    "cursor" : "BtreeCursor field_1",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "field" : [
            [
                {
                    "b" : 1
                },
                {
                    "b" : 1
                }
            ]
        ]
    }
}

请注意,即使您为数组编制了索引,第二个查询也没有索引,但第三个查询却有。根据您打算如何查询数据来选择索引与考虑索引本身是否是您需要的一样重要。在 Mongo 中,如果您不小心,您的索引结构可以并且确实会对查询的性能产生非常大的影响。我认为这解释了你的第一个问题。

您的第二个问题有点开放式,但我认为答案再次在于您期望如何查询数据。如果您只对匹配“fields.a”的值感兴趣,那么您应该为将来可能需要的其他索引节省内存空间。但是,如果您同样可能查询数组中的任何这些项目,并且您有理由确定数组不会无限增长(永远不要对可能会随着时间增长到无限大小的数组进行索引。索引一旦数组在 BSON 中达到 1024 个字节,将无法索引文档。),那么您应该索引整个数组。这方面的一个例子可能是一手扑克牌的文档,其中包含描述用户手中每张牌的数组。

于 2012-11-27T13:34:51.433 回答