当前位置: 首页 > 知识库问答 >
问题:

Mongo find查询需要2分钟

应安国
2023-03-14

我收集了大约75000份文件。

数据库的总大小约为45GB
在75k个文档中,约45k个文档的大小分别为900 KB(约42 GB),其余文档的大小分别约为120 KB。

每个文档都映射到其他集合中的CustIdObjectId,并具有一个时间戳,两者都已索引。

现在,我需要获取上个月特定客户ID的文档。数量约为5500份文件。这个custId包含大小约为120 KB的小文档。

以下是我的查询:

db.mycollection.find(
{
    custId:ObjectId("CUST_OBJECT_ID_HERE"),
    timestamp:{$gte:one_month_ago_date, $lt:current_date}
}).sort({timestamp:-1})

不过,查询需要2分钟才能获取所有记录。是因为文件的数量还是较大文件的大小?有什么办法可以解决这个问题吗?

注意:从nodejs启动查询需要2分钟。如果我在mongo shell上启动它,它会很快返回,但可能是因为它只获取了前50条记录。当我附加<代码>。count()对于mongo shell上的查询,返回计数需要2分钟。

更新:索引详细信息:

"wiredTiger" : {
    "nindexes" : 3,
    "totalIndexSize" : 2396160,
    "indexSizes" : {
        "_id_" : 1138688,
        "custId_1" : 598016,
        "timestamp_1" : 659456
    }
}

解释输出:(带排序)

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "mydb.mycollection",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [
                {
                    "custId" : {
                        "$eq" : ObjectId("CUST_OBJECT_ID_HERE")
                    }
                },
                {
                    "timestamp" : {
                        "$lt" : ISODate("2017-05-15T14:20:04.393Z")
                    }
                },
                {
                    "timestamp" : {
                        "$gte" : ISODate("2017-04-15T14:20:04.393Z")
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "custId" : {
                    "$eq" : ObjectId("CUST_OBJECT_ID_HERE")
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "timestamp" : 1
                },
                "indexName" : "timestamp_1",
                "isMultiKey" : false,
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 1,
                "direction" : "backward",
                "indexBounds" : {
                    "timestamp" : [
                        "(new Date(1494858004393), new Date(1492266004393)]"
                    ]
                }
            }
        },
        "rejectedPlans" : [
            {
                "stage" : "SORT",
                "sortPattern" : {
                    "timestamp" : -1
                },
                "inputStage" : {
                    "stage" : "SORT_KEY_GENERATOR",
                    "inputStage" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "$and" : [
                                {
                                    "timestamp" : {
                                        "$lt" : ISODate("2017-05-15T14:20:04.393Z")
                                    }
                                },
                                {
                                    "timestamp" : {
                                        "$gte" : ISODate("2017-04-15T14:20:04.393Z")
                                    }
                                }
                            ]
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "custId" : 1
                            },
                            "indexName" : "custId_1",
                            "isMultiKey" : false,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {
                                "custId" : [
                                    "[ObjectId('CUST_OBJECT_ID_HERE'), ObjectId('CUST_OBJECT_ID_HERE')]"
                                ]
                            }
                        }
                    }
                }
            }
        ]
    },
    "serverInfo" : {
        "host" : "test-machine",
        "port" : 27017,
        "version" : "3.2.12",
        "gitVersion" : "REMOVED_BY_OP"
    },
    "ok" : 1
}

共有3个答案

仉英朗
2023-03-14

上面的答案都是完全正确的。只是要投入我的2美分。这个答案在很大程度上取决于你的可用存储器,以及你需要返回的信息是否是“实时的”,或者信息可以以某种方式缓存。

Mongodb因内存使用而臭名昭著。(我喜欢mongodb,但记忆是致命的弱点)。第二,如前所述,在进行查询之前,可以改进查询结果的任何操作在时间、读取和核心使用方面都是一个很大的优势。当涉及到文档存储时,您可能(或将)找到一个正确设置的Redis缓存,这也将极大地帮助您降低响应时间。

显然,这需要内存,在您的情况下需要平衡(包括负载平衡)。它是内存、速度和磁盘使用的适当组合(即使是SSD),这将帮助您平衡这些查询请求与系统要求。

希望这有点帮助。

袁桐
2023-03-14

试试这个索引

db.mycollection.createIndex({custId:1,timestamp:1}, {background:true})
糜正业
2023-03-14

这就是索引的作用!

为时间戳和CustId创建索引(两者的复合索引将是最有效的),你就可以了。由于按时间戳排序,在复合索引中,将时间戳设为第一个(顺序很重要)

这是在mongo中创建复合索引的代码:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
    //...
});

userSchema.index({timestamp: 1, custId: 1});

mongoose.model('User', userSchema);
module.exports = userSchema;
 类似资料:
  • 问题内容: 一个菜鸟MYSQL用户....我有一个简单的MySQL查询,该查询返回值,并使用GROUP_CONCAT函数: 但是,我需要转置查询,以便它以单独的列而不是行的形式返回“名称”。MySQL完全有可能吗? 问题答案: 您需要执行一项操作,MySQL本身不支持该操作(与某些其他RDBMS不同)。 您可以获得的最接近的结果是按照以下几行构造SQL: 如果可能的值是动态的,则可以从以下结果中以

  • 我在云Firestore里查询了一下, 我收到了错误,但我有一个索引。

  • 我正在建设聊天应用程序与后端firestore数据库与下面的结构。 我正在获取下面提到的数据。它返回我的用户id在字段“UserArray”中涉及的通道列表,并根据给定的日期/时间获取“LASTUPDATEDON”数据。 在上面的例子中,它显示了我在android logcat中创建复合索引的错误。复合索引创建完成,但仍得到相同的错误消息。

  • 我这里有3个实体A、B和C。 实体A和实体B都与实体C有关系。在我的例子中,我有一个来自实体A的当前id,并且我想使用来自实体C的查询到达实体B。 多谢了。

  • 几个月前,我在使用java.sql时了解到了这一点。连接我需要关闭PreparedStatements和ResultSet,以防止内存泄漏,如下所述 然而,我最近开始与一个使用org.sql2o的新团队合作。连接,这是一个很好且有用的jdbc包装器,但我注意到它们通常不会关闭其org.sql2o。查询对象。 如您所见,查询对象从未显式关闭。我认为最好同时关闭查询: 但我不确定这是否真的有必要。如果

  • 我现在在大学学习数据库,在我的项目中,我有3个表:、和 联赛(leagueId,leagueName) 团队(teamId,teamName) 具有(leagueId,teamId,year)