官网资料:$sort
其它资料:聚合管道优化
$match + $project
当管道的顺序为 $project → $match 时,优化器会将 $match 提前到 $project 前面去执行。
例如,管道包括如下阶段:
{ $project: { status: 1, name: 1 } },
{ $match: { age : 18 } }
优化器优化后,会变成:
{ $match: { age : 18 } },
{ $project: { status: 1, name: 1 } }
类似的操作包括:$match 与 $sort
$sort + $limit
当管道的顺序为 $sort → $limit 时,且中间没有修改文档数量的其它操作(如:$group、$unwind),优化器会将 $limit 合并到 $sort 中。
例如,管道包括如下阶段:
{ $sort : { age : -1 } }, { $project : { age : 1, status : 1, name : 1 } }, { $limit: 5 }
优化器优化后,会合并成:
{ "$sort" : { "sortKey" : { "age" : -1 }, "limit" : NumberLong(5) } }, { "$project" : { "age" : 1, "status" : 1, "name" : 1 } }
这样, $sort 操作在进行时只维护前 n 个结果(也就是说得到前n个结果就停止排序),其中 n 为limit数量。当 allowDiskUse 为true并且n项超过内存限制时,此优化仍然使用
$sort + $skip + $limit
当管道的顺序为 $sort → $skip → $limit 时,优化器会将 $limit 提前到 $skip 前面去执行,此时$limit = 优化前的$limit + 优化前的$skip。
例如,管道包括如下阶段:
{ $sort: { age : -1 } }, { $skip: 10 }, { $limit: 5 }
优化器优化后,会变成:
{ "$sort" : { "sortKey" : { "age" : -1 }, "limit" : NumberLong(15) } }, { "$skip" : NumberLong(10) }
说明:当skip小时,这样分页会很快。但是当skip很大时,limit的个数还是很多,所以分页还是很慢。
$project + $skip
当管道的顺序为 $project → $skip 时,优化器会将 $skip 提前到 $project 前面去执行。
例如,管道包括如下阶段:
{ $sort: { age : -1 } }, { $project: { status: 1, name: 1 } }, { $skip: 5 }
优化器优化后,会变成:
{ $sort: { age : -1 } }, { $skip: 5 }, { $project: { status: 1, name: 1 } }