为什么MongoDB的“$和”运算符有时使用不同的计划而不是内联指定标准?

时间:2014-02-04 19:31:59

标签: mongodb

在我看来,以下两个查询应该具有完全相同的“解释”输出:

查询1:

{
    $and: [
        { $or: [
            { Foo: "123" },
            { Bar: "456" }
        ] },
        { Baz: { $in: ["abc", "def"] } }
    ]
}

查询2:

{
    $or: [
        { Foo: "123" },
        { Bar: "456" }
    ],
    Baz: { $in: ["abc", "def"] } }
}

请注意,我在{ Foo: -1, Baz: -1 }{ Bar: -1, Baz: -1 }上有索引,因此针对$or运算符进行了优化。事实上,在查询2的版本中,在解释输出中,我看到两个clauses,两个都有适当的索引边界,一个用于(Foo, Baz),一个用于(Bar, Baz)。 MongoDB正在做它应该做的事情。

但是在第一个版本(查询1)中,不再有clauses。它给了我一个没有指定索引边界的BasicCursor

这两个查询有什么区别?为什么Mongo似乎能够优化#2而不是#1?

现在我正在使用MongoVue测试这些查询,所以我可以控制JSON,但最终我将使用C#驱动程序,我很确定它将始终在#1中发出语法而不是#2,所以找出正在发生的事情很重要......

1 个答案:

答案 0 :(得分:4)

这似乎是mongodb中的某种错误。你用的是哪个版本?

根据that bug report,问题已在2.5.3解决。

在我们转到更高版本(我2.4.6之前)之前,我们必须小心使用$and运算符。

我也会在2.6尝试。

更新:

事实上,我现在已经修复了2.6.3。

> db.test.find()
{ "_id" : 1, "Fields" : { "K1" : 123, "K2" : 456 } }
{ "_id" : 2, "Fields" : { "K1" : 456, "K2" : 123 } }
> db.test.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.test"
    },
    {
        "v" : 1,
        "key" : {
            "Fields.K1" : 1
        },
        "name" : "Fields.K1_1",
        "ns" : "test.test"
    },
    {
        "v" : 1,
        "key" : {
            "Fields.K2" : 1
        },
        "name" : "Fields.K2_1",
        "ns" : "test.test"
    }
]

> db.test.find({"$and" : [{ "Fields.K1" : 123, "Fields.K2" : 456}]}).explain()
{
    "cursor" : "BtreeCursor Fields.K1_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 4,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "Fields.K1" : [
            [
                123,
                123
            ]
        ]
    },
    "server" : "benihime:27017",
    "filterSet" : false
}
> db.test.find({ "Fields.K1" : 123, "Fields.K2" : 456}).explain()
{
    "cursor" : "BtreeCursor Fields.K1_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 4,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "Fields.K1" : [
            [
                123,
                123
            ]
        ]
    },
    "server" : "benihime:27017",
    "filterSet" : false
}