我有一个包含300万份文档和以下索引的集合:
{ts:1},{u_id:1}
请注意,这些是两个单独的升序索引,而不是复合索引。
当我运行此查询时:
db.collection.find({u_id:' user'})。sort({ts:-1})。skip(0).limit(1)
需要+ 100ms。我有以下日志:
2017-04-15T06:42:01.147 + 0000 I COMMAND [conn783]查询
db.collection查询:{orderby:{ts:-1},$ query:{
u_id:" user-ki-id}} planSummary:IXSCAN {u_id:
1},IXSCAN {u_id:1} ntoreturn:1 ntoskip:0 keysExamined:10795
docsExamined:10795 hasSortStage:1 cursorExhausted:1 keyUpdates:0
writeConflicts:0 numYields:86 nreturned:1 reslen:771 locks:{Global:{
acquireCount:{r:174}},数据库:{acquireCount:{r:87}},
收集:{acquireCount:{r:87}}} 246ms
关于这个问题的一些值得注意的要点:
所以我的问题是:
当我在这个集合上运行范围搜索时,也会发生同样的事情;这需要3-5秒。
修改 我只添加{u_id:1,ts:-1}索引。删除所有其他索引(_id除外)。仍然在第一次执行查询执行+ 100毫秒。这不应该发生 查询:
db.getCollection(' locations')。find({u_id:" USR-WOWU"}) .sort({ts:-1})。explain(true)
OutPut ::
/ * 1 * / { " queryPlanner" :{ " plannerVersion" :1, "命名空间" :" db_name.collection_name", " indexFilterSet" :假的, " parsedQuery" :{ " USER_ID" :{ " $当量" :" USR-WOWU" } }, " winningPlan" :{ "级" :" FETCH", " inputStage" :{ "级" :" IXSCAN", " keyPattern" :{ " U_ID" :1.0, " TS" :-1.0 }, " INDEXNAME" :" u_id_1_ts_-1", " isMultiKey" :假的, " isUnique设置" :假的, " isSparse" :假的, " isPartial" :假的, " indexVersion" :1, "方向" :"转发", " indexBounds" :{ " U_ID" :[ " [\" USR-WOWU \",\" USR-WOWU \"]" ] " TS" :[ " [MaxKey,MinKey]" ] } } }, " rejectedPlans" :[] }, " executionStats" :{ " executionSuccess" :真的, " nReturned" :164, " executionTimeMillis" :119, " totalKeysExamined" :164, " totalDocsExamined" :164, " executionStages" :{ "级" :" FETCH", 的" nReturned" :164, 的" executionTimeMillisEstimate" :120, "工作" :165, "高级" :164, " needTime" :0, " needYield" :0, " saveState和" :3, " restoreState" :3, " isEOF" :1, "无效信号" :0, " docsExamined" :164, " alreadyHasObj" :0, " inputStage" :{ "级" :" IXSCAN", " nReturned" :164, " executionTimeMillisEstimate" :0, "工作" :165, "高级" :164, " needTime" :0, " needYield" :0, " saveState和" :3, " restoreState" :3, " isEOF" :1, "无效信号" :0, " keyPattern" :{ " U_ID" :1.0, " TS" :-1.0 }, " INDEXNAME" :" u_id_1_ts_-1", " isMultiKey" :假的, " isUnique设置" :假的, " isSparse" :假的, " isPartial" :假的, " indexVersion" :1, "方向" :"转发", " indexBounds" :{ " U_ID" :[ " [\" USR-WOWU \",\" USR-WOWU \"]" ] " TS" :[ " [MaxKey,MinKey]" ] }, " keysExamined" :164, " dupsTested" :0, " dupsDropped" :0, " seenInvalidated" :0 } }, " allPlansExecution" :[] }, " serverInfo" :{ "主机" :" manish", "端口" :22022, "版本" :" 3.2.13", " gitVersion" :" 23899209cad60aaafe114f6aea6cb83025ff51bc" }, " OK" :1.0}
请将以上jSON和格式复制到任何编辑器中。
在上述查询之后,下一个相同的查询将在~2 ms内响应。但是当我进行少量插入时,一分钟之后会重复同样的事情。 (第一次查询需要时间+ 100ms,然后需要~2ms。)
在我的mongoDB中配置是否缺少或需要配置什么?
答案 0 :(得分:2)
为什么会这样?
此日志行的docsExamined:10795
和hasSortStage:1
部分表示查询正在从磁盘扫描10,795,然后将结果排序到内存中。可以找到解释日志行的指南here。
indexing this query to avoid the in-memory sort可能会提高绩效。
对于此查询,您应该尝试创建索引{ 'u_id' : 1, 'ts' : -1 }
。
如果我按降序改变{ts:-1}之类的索引,那真的是值得的。
可以在任一方向读取索引,因此索引顺序对单个字段索引不是非常重要。但是,排序顺序在compound indexes中非常重要。
根据解释计划,查询现在正确使用索引按顺序读取索引中的结果,这样可以避免内存中的排序。看起来这个问题已经被淘汰了大约100毫秒。
但是,此查询似乎不再使用.skip(0).limit(1)
。您可以重新添加这些并查看性能是否有所改善?
您的部署似乎没有任何问题;对于未完全索引的查询,此行为似乎正常。
重新运行完全相同的查询将很快,因为现有结果(“the working set”)已经存储在内存中。插入新数据可能会使查询结果发生变化,这意味着结果可能需要再次读回内存。