1

我今天早上的大部分时间都在重新阅读她的 MongoDB文档博客和其他答案,但我仍然错过了一些我希望对其他人来说非常明显的东西。

编辑:我已将文档的方案更改为没有子文档(元数据。*),并且仍然存在未覆盖索引的问题。我删除了现有索引并用新索引重新索引:

所以不是我有:

[
    {
        "v" : 1,
        "key" : {
                "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.daily"
    },
    {
        "v" : 1,
        "key" : {
                "host" : 1,
                "cid" : 1,
                "title" : 1,
                "urls" : 1,
                "global" : -1,
                "current" : -1,
                "total" : -1
        },
        "name" : "byHostTotals",
        "ns" : "test.daily"
    },
    {
        "v" : 1,
        "key" : {
                "host" : 1,
                "cid" : 1,
                "title" : 1,
                "urls" : 1,
                "total" : -1,
                "global" : -1,
                "current" : -1
        },
        "name" : "byHostCurrents",
        "ns" : "test.daily"
    }
]

并给出这个查询:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10).explain()

未显示为被名为“byHostCurrent”的索引所覆盖:

{
    "clauses" : [
        {
            "cursor" : "BtreeCursor byHostCurrents",
            "isMultiKey" : true,
            "n" : 10,
            "nscannedObjects" : 1090,
            "nscanned" : 1111,
            "scanAndOrder" : true,
            "indexOnly" : false,
            "nChunkSkips" : 0,
            "indexBounds" : {
                "host" : [
                        [
                            "example.com",
                            "example.com"
                        ]
                ],
                "cid" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ],
                "title" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ],
                "total" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ],
                "global" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ],
                "current" : [
                    [
                        {
                            "$maxElement" : 1
                        },
                        {
                            "$minElement" : 1
                        }
                    ]
                ]
            }
        },
        {
            "cursor" : "BtreeCursor ",
            "isMultiKey" : false,
            "n" : 0,
            "nscannedObjects" : 0,
            "nscanned" : 0,
            "scanAndOrder" : true,
            "indexOnly" : false,
            "nChunkSkips" : 0,
            "indexBounds" : {
                "host" : [
                        [
                                "usatoday.com",
                                "usatoday.com"
                        ]
                ],
                "cid" : [
                    [
                        {
                                "$minElement" : 1
                        },
                        {
                                "$maxElement" : 1
                        }
                    ]
                ],
                "title" : [
                    [
                        {
                                "$minElement" : 1
                        },
                        {
                                "$maxElement" : 1
                        }
                    ]
                ],
                "total" : [
                    [
                        {
                                "$maxElement" : 1
                        },
                        {
                                "$minElement" : 1
                        }
                    ]
                ],
                "global" : [
                    [
                        {
                                "$maxElement" : 1
                        },
                        {
                                "$minElement" : 1
                        }
                    ]
                ],
                "current" : [
                    [
                        {
                                "$maxElement" : 1
                            },
                            {
                                "$minElement" : 1
                            }
                        ]
                    ]
                }
            }
        ],
    "cursor" : "QueryOptimizerCursor",
    "n" : 10,
    "nscannedObjects" : 1090,
    "nscanned" : 1111,
    "nscannedObjectsAllPlans" : 1090,
    "nscannedAllPlans" : 1111,
    "scanAndOrder" : false,
    "nYields" : 8,
    "nChunkSkips" : 0,
    "millis" : 9,
    "server" : "ubuntu:27017",
    "filterSet" : false
}

MongoDB版本是:2.6.3。

4

1 回答 1

3

所以这里是瘦...

查询时:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10);

如果我没有 .sort() ,它将使用索引,但是由于我现在使用排序,因此索引字段的顺序变得很重要。

为了使上述查询使用索引,我需要像这样创建一个新索引:

db.daily.ensureIndex({'current': -1, 'host': 1, 'cid': 1, 'title': 1}); 

现在有了这个索引,我们将得到 indexOnly: true ,因为我们以相反的顺序(降序)查看总电流,我们只需要扫描索引中所需的条目即可满足 ' host' = 'example.com' 和限制要求。

所以总的来说,我必须有 4 个额外的索引来支持我的查询:

  1. 一个查找内容 ID 与最新的人就可以了(上面的索引)
  2. 一个查找拥有最多人的内容 ID(如上,但总数:-1 而不是当前:-1)
  3. 一个按当前排序的主机查找内容(请参阅下面的索引),并且,
  4. 一种按主机查找内容,按总数排序(如下所示)

    db.daily.ensureIndex({'host': 1, 'current': -1, 'cid': 1, 'title': 1});

所以 MongoDB 文档对这些事情的解释不是很清楚,尤其是在查看排序问题时。他们没有说的是,如果您要使用排序,则必须在相等查询之后包含前缀字段或包含所有前缀字段。

例如,从我的问题中给出我的原始索引:

db.daily.ensureIndex({"host" : 1, "cid" : 1, "title" : 1, "urls" : 1, "global" : -1, "current" : -1, "total" : -1});

如果我希望索引覆盖一个查询,那么我必须对此进行更改:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'current': -1}).limit(10);

对此:

db.daily.find({'host': 'example.com'}, {'_id': 0, 'cid': 1, 'title': 1, 'current': 1}).hint("byHostCurrents").sort({'cid':1, 'title':1, 'urls': 1, 'global: 1, 'current': -1}).limit(10);

这不是我想要的。

希望这对将来的某人有所帮助。

于 2014-08-07T17:01:27.013 回答