db.inventory.find().limit(10)
比db.inventory.find()
更快吗?
我在mongodb有数百万条记录,我希望在某些订单中获得前10名记录。
答案 0 :(得分:2)
使用limit()
通知服务器您不会检索超过 k 的文档。允许一些优化以减少带宽消耗并加速排序。最后,使用限制子句,服务器将能够更好地使用在RAM中排序时可用的32MB最大值(即:当无法从索引获取排序顺序时)。
现在,长篇故事:find()
返回一个光标。默认情况下,光标会将结果批量传输到客户端。来自the documentation,:
对于大多数查询,第一批返回101个文档或只有足够的文档超过1兆字节。后续批量大小为4兆字节。
使用limit()
光标不需要检索超过必要的文档。从而减少带宽消耗和延迟。
请注意,根据您的使用案例,您可能也会使用sort()
操作。从上面的相同文档:
对于包含没有索引的排序操作的查询,服务器必须加载内存中的所有文档以在返回任何结果之前执行排序。
sort() documentation page进一步解释:
如果MongoDB无法通过索引扫描获得排序顺序,那么MongoDB使用top-k排序算法。此算法缓冲底层索引或集合访问到目前为止看到的前k个结果(或最后一个,具体取决于排序顺序)。如果在任何时候这些k结果的内存占用超过32兆字节,则查询将失败 1 。
1 该32 MB限制并非特定于使用limit()
子句进行排序。无法从索引获得其顺序的任何类型都将受到相同的限制。但是,使用 plain 排序服务器需要在其内存中保存所有文档以对其进行排序。使用限制排序时,只需将 k 文档同时存储在内存中。
答案 1 :(得分:0)
如果您按顺序需要它,那么DB当然会先根据条件对其进行排序,然后返回前10条记录。通过使用限制,您只需节省网络带宽。例如在这里我按名称排序,然后给出前10条记录,它必须扫描整个数据,然后选择前10名。(你可以注意到它做了COLLSCAN,这是理解为收集扫描,因为我没有索引对于这个例子,这里显示的想法是它对所有记录进行全面扫描,对其进行排序,然后选择最顶层的记录。)
> db.t1.find().sort({name:1}).limit(10).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.t1",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"name" : 1
},
"limitAmount" : 10,
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : [ ]
},
"direction" : "forward"
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "Sachin-Mac.local",
"port" : 27017,
"version" : "3.0.2",
"gitVersion" : "6201872043ecbbc0a4cc169b5482dcf385fc464f"
},
"ok" : 1
}