我正在运行一个非常普通的MongoDB查询,没有什么真正的复杂或特殊的,我想知道它花费的时间(> 1秒)是否正常或我的索引是否有问题。
我为此特定查询提供了一个索引,explain()
也告诉我它已被使用,但它每次都会对集合进行全面扫描,并通过>减慢整个网页的速度。 1秒。
查询:
db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"})
说明:
> db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"}).explain()
{
"cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1",
"nscanned" : 21306,
"nscannedObjects" : 21306,
"n" : 21306,
"millis" : 1180,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
"art_filter" : [
[
null,
null
]
],
"art_hauptartikelnr" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
}
索引:
{
"v": 1,
"key": {
"art_filter": 1,
"art_hauptartikelnr": 1
},
"ns": "togshop.tog_artikel",
"background": true,
"name": "art_filter_1_art_hauptartikelnr_1"
}
为什么每次都会扫描整个集合?为什么isMultiKey
为false,我如何优化此查询/索引?
环境是一个独立的服务器,MongoDB 2.0.1,64位Linux,可以从PHP w / php-mongo 1.2.6访问
答案 0 :(得分:7)
为什么每次都要扫描整个集合?
不是。它正在通过索引:
"cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1",
这意味着索引“art_filter_1_art_hauptartikelnr_1”用于满足$ exists条件。
如果该过滤器不是非常有选择性(即有许多记录满足它),查询仍然会花费很多时间。
为什么isMultiKey为false
它是错误的,因为没有使用多键索引。多键索引是包含以数组作为值的字段的索引。它与索引是复合的(即具有多个字段)无关。
$where":"this._id == this.art_hauptartikelnr"
你的第二个条件是Javascript表达式,这里不能使用索引(因为查询分析器不理解你在做什么)。 即使它确实如此,您也需要一个也包含_id的索引。
如何优化此查询/索引?
将您的数据归一化为具有值为true或false的新字段“idIsHauptArtikelNr”。 在(art_filter,idIsHauptArtikelNr)上创建索引,并用
替换您的查询 { art_filter :{ $exists :false}, idIsHauptArtikelNr : true }