1

我有一系列课程,其中包含具有以下架构的文档

{
    title: "Programming 101",
    category: 1
    likes: 10,
    author: {
        name: "Mike",
        reputation: 100,
        rating: 1500
    },
    created: 154895126, // unix timestamp
    content: ".... html ... "
}

在我的应用程序的索引页面中,我显示了所有类别的最新 18 节课,所以这是

db.lessons.find().sort({created:-1}).limit(18)

由于这是一个非常常见的查询,而课程集合将是我在系统中最大的集合,我想尽可能地优化它,所以我在created上做了一个索引

db.lessons.ensureIndex({created:-1})

但有时我只想从一类中得到教训

db.lessons.find({category:1}).sort({created:-1}).limit(18)

所以我还在类别中添加了一个索引,因为如果我不这样做,mongo可以轻松排序,但它仍然需要逐个元素检查才能获得类别= 1的那个,所以

db.lessons.ensureIndex({category:1})

因为我不按类别排序,所以我只传递一个 1,用于升序。

现在,问题是我还想按点赞、作者声望和作者评分对课程进行排序,这些将是非常常见的任务,不像按创建排序那样常见,但仍然很常见,我是否应该再添加 3 个索引?还是只使用创建的?

db.lessons.ensureIndex({likes:-1})
db.lessons.ensureIndex({'author.reputation':-1})
db.lessons.ensureIndex({'author.rating':-1})

我觉得我可能使用了太多索引,并且内存中的集合大小可能很大。

4

2 回答 2

4

我将第三次 asya 提出聚合索引的动议。

> db.lessons.ensureIndex({category:1});
> db.lessons.ensureIndex({created:-1});
> db.lessons.find({category:1}).sort({created:-1}).limit(18).explain();
{
    "cursor" : "BtreeCursor category_1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "scanAndOrder" : true,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
        "category" : [
            [
                1,
                1
            ]
        ]
    }
}

这里的 explain() 说明 MongoDB 不会像我们期望的 SQL 数据库那样使用两个单独的索引。

> db.lessons.ensureIndex({category:1,created:-1});
> db.lessons.find({category:1}).sort({created:-1}).limit(18).explain();
{
    "cursor" : "BtreeCursor category_1_created_-1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
        "category" : [
            [
                1,
                1
            ]
        ],
        "created" : [
            [
                {
                    "$maxElement" : 1
                },
                {
                    "$minElement" : 1
                }
            ]
        ]
    }
}

综合指数看起来肯定是赢家。

至于对索引过多的担忧,对于我的日常工作,我正在处理一个集合,该集合包含超过 3800 万个文档,通过 --notablescan 选项禁用了表扫描。我们发现,为每个查询量身定制一个索引对我们来说至关重要。

于 2012-11-23T19:59:49.427 回答
0

如果你提到那个

这些将是非常常见的任务

在我看来,您应该使用索引,否则您的查询将在给出结果之前遍历您集合中的所有文档。当然,要更准确地回答,必须知道您的收藏数量,当然还有一些关于“常见事物”的指标。并且可以肯定,决定你应该如何表现的最好方法是运行一些测试。

收集用户在一段时间(2 天)内的行为信息,并检查每种类型的查询出现了多少次。比你现在每一个的“共性”。比使用和不使用索引模拟这些类型的查询并检查什么效果更好。

我也同意@Asya 关于这里的回复

您的第二个索引不是 {category:1, created:-1} 有什么原因吗

于 2012-11-22T21:06:01.143 回答