未索引数字字段上$lt/$gt查询比$eq快的原因探究
未索引字段聚合查询中$lt/$gt比$eq快的原因分析
前提回顾
集合包含150万条文档,字段B是未索引的数字字段,取值为1到1000的随机数,每个数值对应的文档数约1500条(150万÷1000)。
核心性能差异原因
因为字段B未索引,$match阶段必须执行全表扫描(COLLSCAN),而性能差异的关键在于**$limit阶段触发的扫描终止逻辑**:
- 当使用
$lt:500或$gt:500时:
符合条件的文档占总数据量的近一半(前者约49.9%,后者约50%)。MongoDB在扫描文档时,每找到一条符合条件的记录就会传递给$limit阶段,一旦凑够1000条符合要求的文档,整个扫描过程会立刻停止。实际只需要扫描约2000条文档就能满足$limit,扫描量极小。 - 当使用
$eq:500时:
符合条件的文档仅占总数据的0.1%(1/1000),且随机分散在整个集合中。MongoDB必须持续扫描大量文档,直到凑齐1000条B=500的记录为止。平均需要扫描约100万条文档才能达标,扫描量是前者的数百倍,因此速度慢5-10倍。
补充说明
如果去掉$limit阶段,三种查询的速度会基本一致——因为都需要完成全表扫描来匹配所有符合条件的文档。$limit的存在才让$lt/$gt的提前终止逻辑生效,放大了性能差异。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

