MongoDB在仅返回_id时使用COLLSCAN

MongoDB在仅返回_id时使用COLLSCAN,mongodb,mongodb-indexes,Mongodb,Mongodb Indexes,我想返回MongoDB集合中的所有ID,我使用了以下代码: db.coll.find({}, { _id: 1}) 但是MongoDB扫描整个集合,而不是从默认的索引{u id:1}读取信息 从日志中: { find: "collection", filter: {}, projection: { _id: 1 } } planSummary: COLLSCAN cursorid:30463374118 keysExamined:0 docsExamined:544783 numYields

我想返回MongoDB集合中的所有ID,我使用了以下代码:

db.coll.find({}, { _id: 1})
但是MongoDB扫描整个集合,而不是从默认的
索引{u id:1}
读取信息

从日志中:

{ find: "collection", filter: {}, projection: { _id: 1 } } 
planSummary: COLLSCAN cursorid:30463374118 keysExamined:0
docsExamined:544783 numYields:4286 nreturned:544782 reslen:16777238
locks:{ Global: { acquireCount: { r: 8574 } }, Database: {
acquireCount: { r: 4287 } }, Collection: { acquireCount: { r: 4287 } }
} protocol:op_query 7024ms

您知道如何解决这个问题吗?

您需要添加一个可以像这样使用此索引的筛选器,以便更改该查询计划-并非所有操作都会删除提取阶段,例如,$exists似乎不起作用:

db.coll.find({ _id: { $ne: 0 }, { _id: 1 }) // works for ObjectIds
对此的一部分解释如下:

覆盖查询是完全可以使用 索引,无需检查任何文档。索引包括 当以下两项都适用时进行查询:

  • 查询中的所有字段都是索引的一部分
  • 结果中返回的所有字段都在同一索引中

我似乎记得看到一个JIRA请求在没有过滤器的情况下支持该请求,但记不起是哪张票证…

我找到了一个解决方案,如果知道
\u id
字段的类型,该解决方案就会起作用。如果是字符串
\u id

db.coll.find({ _id: { $regex: ".*" }, { _id: 1 })
db.coll.find({ _id: { $gte: 0 }, { _id: 1 })
如果是整数
\u id

db.coll.find({ _id: { $regex: ".*" }, { _id: 1 })
db.coll.find({ _id: { $gte: 0 }, { _id: 1 })

您使用的MongoDB服务器的具体版本是什么?因为您没有指定任何查询条件或排序顺序,所以迭代的最快计划通常是(但不总是)按自然顺序进行集合扫描。有关背景详细信息,请参阅和链接问题。在
\u id
上添加排序顺序或提示将导致使用投影进行覆盖索引查询。为了比较,你可以试试:
db.coll.find({},{u-id:1}).sort({u-id:1})
)?Stennie,谢谢
db.coll.find({},{u-id:1}).sort({u-id:1})
真的有效!另外,
.hint({u id:1})
按照您在其他评论中的建议工作:谢谢,但不幸的是,
$exists:true
没有跳过获取阶段,该阶段读取集合中的所有文档。true。我只是查看日志输出,看看是否使用了索引,而不是完整的执行计划……您还可以使用
sort({u id:1})
hint()
,正如我在对问题的评论中所建议的那样。