我在集合中有大约1000000个文档(随机生成)。
示例文件:
{
"loc": {
"lat": 39.828475,
"lon": 116.273542
},
"phone": "",
"keywords": [
"big",
"small",
"biggest",
"smallest"
],
"prices": [
{
"category": "uRgpiamOVTEQ",
"list": [
{
"price": 29,
"name": "ehLYoPpntlil"
}
]
},
{
"category": "ozQNmdwpwhXPnabZ",
"list": [
{
"price": 96,
"name": "ITTaLHf"
},
{
"price": 88,
"name": "MXVgJFBgtwLYk"
}
]
},
{
"category": "EDkfKGZSou",
"list": [
{
"price": 86,
"name": "JluoCLnenOqDllaEX"
},
{
"price": 35,
"name": "HbmgMDfxCOk"
},
{
"price": 164,
"name": "BlrUD"
},
{
"price": 106,
"name": "LOUcsMDeaqVm"
},
{
"price": 14,
"name": "rDkwhN"
}
]
}
],
}
无索引搜索
> db.test1.find({"prices.list.price": { $gt: 190 } }).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 541098,
"nscannedObjects" : 1005584,
"nscanned" : 1005584,
"nscannedObjectsAllPlans" : 1005584,
"nscannedAllPlans" : 1005584,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 8115,
"nChunkSkips" : 0,
**"millis" : 13803,**
"server" : "localhost:27017",
"filterSet" : false
}
使用索引:
> db.test1.ensureIndex({"prices.list.price":1,"menu.list.name":1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.test1.find({"prices.list.price": { $gt: 190 } }).explain()
{
"cursor" : "BtreeCursor prices.list.price_1_prices.list.name_1",
"isMultiKey" : true,
"n" : 541098,
"nscannedObjects" : 541098,
"nscanned" : 868547,
"nscannedObjectsAllPlans" : 541098,
"nscannedAllPlans" : 868547,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 16852,
"nChunkSkips" : 0,
**"millis" : 66227,**
"indexBounds" : {
"menu.list.price" : [
[
190,
Infinity
]
],
"menu.list.name" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "localhost:27017",
"filterSet" : false
}
知道为什么索引搜索比没有索引更慢?
我也将使用:
db.test1.find({loc:{$ near:[39.876045,32.862245]}})(需要2d索引)
db.test1.find({keywords:{$ in:[“small”,“another”]}})(使用关键字索引)
db.test1.find({“prices.list.name”:/。 s。 /})(无需索引,因为我将使用正则表达式)
答案 0 :(得分:4)
索引允许更快地访问满足查询的文档位置。
在您的示例中,您的查询选择集合中所有文档的一半。因此,即使索引扫描提供了更快的访问权限,知道哪些文档将与查询谓词匹配,但它实际上会创建更多的工作。
在集合扫描中,查询正在扫描所有文档,并检查您要查询的字段以查看它是否匹配。有一半时间它最终选择了文件。
在索引扫描中,查询遍历所有索引条目的一半,然后直接从它们跳转到满足查询谓词的文档。在你的情况下,这是更多的操作。
此外,在执行此操作时,操作正在产生读取互斥锁,当他们需要等待他们必须读取的文档被带入RAM时,或者当存在等待写入的写入时,以及索引扫描显示收集扫描产量的两倍。如果您的工作集没有足够的RAM,那么添加索引会对现有资源施加更多压力,使速度变慢,而不是更快。
尝试使用与价格相比较大的数字相同的查询,例如500(或者数据集中更具选择性的任何内容)。如果使用索引查询仍然较慢,那么您可能会在系统上看到大量页面错误。但是如果索引有足够的RAM,那么索引查询将很多更快,而未编制索引的查询将同样慢。
答案 1 :(得分:0)
首先,作为建议,在使用elemMatch查询数组时,您将获得更快的速度。 http://docs.mongodb.org/manual/reference/operator/query/elemMatch/ 在你的情况下
db.test1.find({"prices.list.price":{ $elemMatch: { $gte: 190 }} })
第二件事是
要索引包含数组值的字段,MongoDB会添加索引项 对于数组中的每个项目。这些多键索引允许MongoDB 使用数组的值从查询中返回文档。 MongoDB的 如果是,则自动确定是否创建多键索引 索引字段包含数组值;你不需要明确 指定多键类型。
考虑下面的多键索引说明:
addr.zip字段上的多键索引图。 addr字段包含一个数组 地址文件。地址文档包含zip字段。
Multikey索引支持其他MongoDB支持的所有操作 指标;但是,应用程序可能会使用多键索引进行选择 基于数组值的值范围的文档。 多键索引支持包含两个值的数组(例如字符串, 数字)和嵌套文件。