在这个问题的评论中,我知道如何为排序操作创建索引:Mongodb 索引是如何工作的?
但我想知道,当我们在
a
&上创建联合索引时b
,它与简单索引的工作方式有何不同?为什么我们会从发现中受益
a
,但如果我们发现b
,我们不会从中获得任何好处?联合索引是否就像连接a
&一样b
,所以我们将从 Prefix 中受益?
在这个问题的评论中,我知道如何为排序操作创建索引:Mongodb 索引是如何工作的?
但我想知道,当我们在a
&上创建联合索引时b
,它与简单索引的工作方式有何不同?
为什么我们会从发现中受益a
,但如果我们发现b
,我们不会从中获得任何好处?联合索引是否就像连接a
&一样b
,所以我们将从 Prefix 中受益?
1.但我想知道,当我们在'a'&'b'上创建联合索引时,它与简单索引有何不同?
MongoDB 每个查询只使用一个索引 .. 所以如果您的find()
条件同时包含a
和b
值,您应该添加一个复合索引来有效地搜索这两个字段。
2.为什么我们只找到'a'会受益,但如果找到'b',我们不会从中受益?联合索引是否像 concatenate 'a'&'b' 这样我们就可以从 Prefix 中受益?</p>
MongoDB 使用B-tree 索引,因此您只能使用前缀有效地匹配部分键。要查找与后缀或子字符串匹配的所有可能值,必须检查所有索引条目。
下面的例子是使用mongo
shell:
/* 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 复合索引一文。