联合指数如何在mongodb中运作?

hal*_*ack 1 indexing mongodb mongodb-indexes

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

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

  2. 为什么我们只是在寻找中受益a,但如果我们发现b,我们没有从中获益?无论是联合索引就像是串联ab,所以我们会得到好处,从它的前缀?

Ste*_*nie 5

但是我想知道,当我们在'a'和'b'上创建一个联合索引时,它与简单索引有什么区别?

MongoDB每个查询只使用一个索引.因此,如果您的find()条件包含both abvalues,则应添加复合索引以有效搜索这两个字段.

2.为什么我们会好好找到'a',但如果我们找到'b',我们就不会从中得到任何好处?联合索引是否就像连接'a'和'b'一样,所以我们将从它获得前缀的好处?

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

设置测试数据进行比较

以下示例使用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})
}
Run Code Online (Sandbox Code Playgroud)

现在添加一些示例索引:

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

最后,对于下面的测试场景,强制您的查询使用特定索引$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,
    ...
}
Run Code Online (Sandbox Code Playgroud)

搜索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,
    ...
}
Run Code Online (Sandbox Code Playgroud)

技术上扫描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,
    ...
}
Run Code Online (Sandbox Code Playgroud)

对于一些进一步的示例和解释,我建议阅读文章Optimizing MongoDB Compound Indexes.