MongoDB聚合含$or时,索引能否用于排序及阶段是否阻塞?
MongoDB $or场景下的排序与阻塞阶段分析
现有索引
- 复合索引1:
{ A: 1, timestamp: 1 } - 复合索引2:
{ B: 1, timestamp: 1 }
聚合查询语句
db.user.aggregate([ { $match: { $or: [ { A: "some_value" }, { B: "some_value" } ] } }, { $sort: { timestamp: 1 } }, { $limit: 1000 } ])
问题解答
使用$or后,$sort和$limit会成为阻塞阶段,具体原因如下:
- 当
$match使用$or时,MongoDB会分别通过两个复合索引匹配符合条件的文档,之后对两个结果集执行合并去重操作。由于两个索引都是以各自的前缀字段(A或B)+timestamp排序,合并后的结果集整体timestamp是无序的。 - 无
$or的场景下,单个复合索引可以同时满足过滤和排序需求,MongoDB能直接从索引中按timestamp顺序提取数据,无需单独执行排序步骤。但$or场景无法做到这一点,必须先获取所有符合条件的文档,在内存(或磁盘临时文件)中完成全局排序后,才能执行$limit。 - 这就导致
$sort必须等待$match阶段完全结束、拿到所有匹配文档后才能启动,属于阻塞操作;而$limit依赖$sort的结果,自然也会变成阻塞阶段。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

