我有以下嵌入式二级复合指数:
db.people.ensureIndex({"sources_names.source_id":1,"sources_names.value":1})
这是db.people.getIndexes()的一部分:
{
"v" : 1,
"key" : {
"sources_names.source_id" : 1,
"sources_names.value" : 1
},
"ns" : "diglibtest.people",
"name" : "sources_names.source_id_1_sources_names.value_1"
}
所以我运行以下索引覆盖的查询:
db.people.find({ "sources_names.source_id": ObjectId('5166d57f7a8f348676000001'), "sources_names.value": "Ulrike Weiland" }, {"sources_names.source_id":1, "sources_names.value":1, "_id":0} ).pretty()
{
"sources_names" : [
{
"value" : "Ulrike Weiland",
"source_id" : ObjectId("5166d57f7a8f348676000001")
}
]
}
花了大约5秒钟。所以我运行解释:
db.people.find({ "sources_names.source_id": ObjectId('5166d57f7a8f348676000001'), "sources_names.value": "Ulrike Weiland" }, {"sources_names.source_id":1, "sources_names.value":1, "_id":0 }).explain()
{
"cursor" : "BtreeCursor sources_names.source_id_1_sources_names.value_1",
"isMultiKey" : true,
"n" : 1,
"nscannedObjects" : 1260353,
"nscanned" : 1260353,
"nscannedObjectsAllPlans" : 1260353,
"nscannedAllPlans" : 1260353,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 4,
"nChunkSkips" : 0,
"millis" : 4308,
"indexBounds" : {
"sources_names.source_id" : [
[
ObjectId("5166d57f7a8f348676000001"),
ObjectId("5166d57f7a8f348676000001")
]
],
"sources_names.value" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "dash-pc.local:27017"
}
但为什么这个索引覆盖的查询遍历整个数据库?我应该如何创建索引以提高性能?
谢谢!
答案 0 :(得分:0)
您正在多个位置使用多键索引(即sources_names.source_id
),来自文档(http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/#create-indexes-that-support-covered-queries):
如果符合以下情况,索引无法覆盖查询:
集合中任何文档中的任何索引字段都包含一个数组。 如果索引字段是数组,则索引将成为多键索引索引,但不能 支持覆盖查询。
你可以在这里说明这是一个多键索引:
"isMultiKey" : true,
基本上点符号被归类为多键,因为sources_names
是一个数组,因此索引包含一个数组。
至于提高速度:我没有看过这个,但你的问题在这里:
"sources_names.value" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
因此索引没有被最佳地用于查找sources_names.value
。
我认为我刚给出的答案有点奇怪,因为这不应该是一个多键索引,所以我实际上已经测试了这个:
> db.gh.ensureIndex({'d.id':1,'d.g':1})
> db.gh.find({'d.id':5, 'd.g':'d'})
{ "_id" : ObjectId("516826e5f44947064473a00a"), "d" : { "id" : 5, "g" : "d" } }
> db.gh.find({'d.id':5, 'd.g':'d'}).explain()
{
"cursor" : "BtreeCursor d.id_1_d.g_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"d.id" : [
[
5,
5
]
],
"d.g" : [
[
"d",
"d"
]
]
},
"server" : "ubuntu:27017"
}
似乎我原来的想法在哪里,这不应该是一个多键索引。你在value
认为有一些脏数据,这会导致你出现问题。
我会查看您的数据库并确保正确输入您的记录。
你很可能有类似的东西:
{
"sources_names" : [
{
"value" : ["Ulrike Weiland", 1],
"source_id" : ObjectId("5166d57f7a8f348676000001")
}
]
}
有些地方。