使用多个索引在 MongoDB 中加速搜索的最佳方法是什么?
What is the best way to speed up search in MongoDB using multiple indexes?
我有 MongoDB 个包含 50k+ 文档的集合,例如:
{
"_id" : ObjectId("5a42190e806c3210acd3fa82"),
"start_time" : ISODate("2017-12-25T02:29:00.000Z"),
"system" : "GL",
"region" : "NY",
"order_id" : 3,
"task_type" : "px2",
"status" : false
}
当我添加新订单时,Python 脚本会在数据库中搜索具有相同 start_time 和 task_type 的现有订单,例如:
tasks_base.find_one({
"$and": [{
"start_time": plan_date.astimezone(pytz.UTC)
}, {
"task_type": px
}]
})
它有效,但集合中的每个新文档都会减慢它的速度(需要检查更多文档等)。
作为解决方案,我想添加 task_type
和 start_time
作为集合的索引。但有一些顾虑(索引的日期看起来有点不自然)。因此,需要如何正确执行的建议(或其他想法,如何加快搜索速度)。感谢您的任何建议:)
我用 3 个步骤解决了它:
首先,我创建了唯一 compound index:
tasks.create_index([("start_time", pymongo.ASCENDING,), ("task_proxy", pymongo.ASCENDING)], unique=True)
然后,我将查询调整为仅在索引字段中搜索 (covered query):
all_tasks = tasks.find({
"$and": [{
"start_time": {
"$gte": plan_date.astimezone(pytz.UTC),
"$lt": plan_date.astimezone(pytz.UTC) + timedelta(hours=1)
}
}, {
"task_proxy": px
}]
}, {"_id": 0, "start_time": 1, "task_proxy": 1})
最后(上面的代码相同),我将时间查询的大小从 1 分钟增加到 1 小时,因此我可以进行 1 次数据库操作而不是 60 次。我可以使用里面的大部分数据进行操作 Python 脚本,所以数据库的负载要低得多:)
UPD:重写了80%的代码:我每个订单使用1次查询,现在我每小时使用1次查询,在那里找到空闲时间段,然后打包订单空闲单元格(如果没有足够的单元格,则移动到另一个集合)。仍然使用复合索引和覆盖查询,脚本异常时间从 15-17 秒减少到 0.6。
我有 MongoDB 个包含 50k+ 文档的集合,例如:
{
"_id" : ObjectId("5a42190e806c3210acd3fa82"),
"start_time" : ISODate("2017-12-25T02:29:00.000Z"),
"system" : "GL",
"region" : "NY",
"order_id" : 3,
"task_type" : "px2",
"status" : false
}
当我添加新订单时,Python 脚本会在数据库中搜索具有相同 start_time 和 task_type 的现有订单,例如:
tasks_base.find_one({
"$and": [{
"start_time": plan_date.astimezone(pytz.UTC)
}, {
"task_type": px
}]
})
它有效,但集合中的每个新文档都会减慢它的速度(需要检查更多文档等)。
作为解决方案,我想添加 task_type
和 start_time
作为集合的索引。但有一些顾虑(索引的日期看起来有点不自然)。因此,需要如何正确执行的建议(或其他想法,如何加快搜索速度)。感谢您的任何建议:)
我用 3 个步骤解决了它:
首先,我创建了唯一 compound index:
tasks.create_index([("start_time", pymongo.ASCENDING,), ("task_proxy", pymongo.ASCENDING)], unique=True)
然后,我将查询调整为仅在索引字段中搜索 (covered query):
all_tasks = tasks.find({
"$and": [{
"start_time": {
"$gte": plan_date.astimezone(pytz.UTC),
"$lt": plan_date.astimezone(pytz.UTC) + timedelta(hours=1)
}
}, {
"task_proxy": px
}]
}, {"_id": 0, "start_time": 1, "task_proxy": 1})
最后(上面的代码相同),我将时间查询的大小从 1 分钟增加到 1 小时,因此我可以进行 1 次数据库操作而不是 60 次。我可以使用里面的大部分数据进行操作 Python 脚本,所以数据库的负载要低得多:)
UPD:重写了80%的代码:我每个订单使用1次查询,现在我每小时使用1次查询,在那里找到空闲时间段,然后打包订单空闲单元格(如果没有足够的单元格,则移动到另一个集合)。仍然使用复合索引和覆盖查询,脚本异常时间从 15-17 秒减少到 0.6。