You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB Atlas查询扫描/返回对象比值超1000问题求助

MongoDB查询扫描/返回比过高问题解决

问题核心

你收到的Query Targeting: Scanned Objects / Returned has gone above 1000告警,说明查询每次要扫描上千个文档才能返回1个结果,属于性能异常——即便你只是获取最新插入的文档,也触发了全表扫描。

代码问题点

你的实现存在两个关键问题,直接导致了扫描数过高:

  1. 频繁创建销毁MongoClient:每次查询都新建并关闭连接,既浪费资源,也无法利用连接池优化性能。
  2. find()+limit(1)的写法不够高效:虽然逻辑上能拿到最新文档,但这种写法可能让MongoDB无法最优复用_id默认索引,最终触发全表扫描。

解决方案

1. 复用MongoClient连接

MongoClient是线程安全的,应该全局初始化一次,而非每次查询都创建。修改后代码如下:

from pymongo import MongoClient

# 全局初始化连接(仅执行一次)
client = connect_cluster()

class ModelOrderBook():    
    @classmethod
    def get_last_orderbook(cls, symbol):
        try:
            base, quote = symbol.split('/')
            sym = f"{base.lower()}-{quote.lower()}"

            db = client[sym]
            orderbooks = db.orderbooks

            # 用find_one直接获取最新文档,指定按_id降序
            latest_doc = orderbooks.find_one({}, sort=[('_id', -1)])
            return [latest_doc] if latest_doc else []

        except Exception as e:
            raise Exception(e)

2. 强制使用索引(可选)

如果修改写法后仍存在扫描过多文档的情况,可以强制查询使用_id索引:

latest_doc = orderbooks.find_one({}, sort=[('_id', -1)], hint='_id_')

3. 验证索引有效性

在MongoDB Shell中执行以下命令,确认查询是否真的走了索引:

db.orderbooks.find().sort({_id: -1}).limit(1).explain("executionStats")

查看结果中executionStats.totalDocsExamined的值:

  • 若为1,说明索引正常生效;
  • 若仍为上千,需检查:
    • 集合_id字段是否为默认的ObjectId类型(自定义_id会导致默认索引无法按插入时间排序);
    • _id索引是否存在(执行db.orderbooks.getIndexes()查看)。

额外建议

如果业务依赖“按插入时间取最新文档”且自定义了_id,建议新增create_time字段并创建降序索引,后续按该字段排序查询:

// 创建索引
db.orderbooks.createIndex({create_time: -1})

// Python查询写法
latest_doc = orderbooks.find_one({}, sort=[('create_time', -1)])

内容的提问来源于stack exchange,提问作者Miguel Payá

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:16:17