1

在这个问题的评论中,我知道如何为排序操作创建索引:Mongodb 索引是如何工作的?

  1. 但我想知道,当我们在a&上创建联合索引时b,它与简单索引的工作方式有何不同?

  2. 为什么我们会从发现中受益a,但如果我们发现b,我们不会从中获得任何好处?联合索引是否就像连接a&一样b,所以我们将从 Prefix 中受益?

4

1 回答 1

5

1.但我想知道,当我们在'a'&'b'上创建联合索引时,它与简单索引有何不同?

MongoDB 每个查询只使用一个索引 .. 所以如果您的find()条件同时包含ab值,您应该添加一个复合索引来有效地搜索这两个字段。

2.为什么我们只找到'a'会受益,但如果找到'b',我们不会从中受益?联合索引是否像 concatenate 'a'&'b' 这样我们就可以从 Prefix 中受益?</p>

MongoDB 使用B-tree 索引,因此您只能使用前缀有效地匹配部分键。要查找与后缀或子字符串匹配的所有可能值,必须检查所有索引条目。

设置测试数据进行比较

下面的例子是使用mongoshell:

/* Generate some test data */
for (i = 0; i< 1000; i++) {
    db.mycoll.insert({a:i})
    db.mycoll.insert({b:i})
    db.mycoll.insert({a:i,b:i})
}

现在添加一些示例索引:

/* Add simple and compound index */
db.mycoll.ensureIndex({a:1})
db.mycoll.ensureIndex({b:1})
db.mycoll.ensureIndex({a:1, b:1})

最后,对于下面的测试场景,强制您的查询使用特定索引$hint并比较explain()结果。

b使用简单索引搜索

b使用简单索引的搜索b可以直接在索引中找到匹配的条目.. 它扫描 4 个索引条目 ( nscanned) 以返回 4 个结果 ( n):

db.mycoll.find({b:10}).hint({b:1}).explain()
{
    "cursor" : "BtreeCursor b_1",
    "n" : 4,
    "nscannedObjects" : 4,
    "nscanned" : 4,
    ...
}

b使用复合索引搜索(a,b)

b使用复合索引的搜索(a,b)必须检查索引中的每个a值,因为索引的第一部分是 的键值a

因此,要直接在索引中查找匹配条目 .. 它会扫描1904个索引条目 ( nscanned) 以返回 4 个结果 ( n):

db.mycoll.find({b:10}).hint({a:1,b:1}).explain()
{
    "cursor" : "BtreeCursor a_1_b_1",
    "n" : 4,
    "nscannedObjects" : 4,
    "nscanned" : 1904,
    ...
}

从技术上讲,扫描 1,904 个文档少于我的测试集合中的 3,000 个文档......但这远非最佳。

a使用复合索引搜索(a,b)

为了比较,a使用复合索引的搜索表明只需要扫描 4 个值即可返回 4 个文档:

db.mycoll.find({a:10}).hint({a:1,b:1}).explain()
{
    "cursor" : "BtreeCursor a_1_b_1",
    "n" : 4,
    "nscannedObjects" : 4,
    "nscanned" : 4,
    "nscannedObjectsAllPlans" : 4,
    ...
}

对于更多示例和解释,我建议阅读优化 MongoDB 复合索引一文。

于 2012-11-04T04:18:28.687 回答