我正在试图找出创建索引的最佳方法mongo可以用来更快地进行此查询:
"query" : {
"deleted_at" : null,
"placed_at" : {
"$exists" : true
},
"exported_at" : null,
"failed_export" : false
}
目前,即使没有结果,也需要2-3分钟才能完成。解释说明它正在查看数十万条记录而不使用索引。
我试过这个:
db.some_table.createIndex({deleted_at: -1, placed_at: 1, exported_at: -1, failed_export: -1}, {background: true})
之后我运行查询:
db.some_table.find({deleted_at: null, placed_at: {$exists: true}, exported_at: null, failed_export: false}).explain("executionStats")
我看到它正在使用正确的索引,但它非常慢。它正在检查所有330494行。以下是执行统计数据:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 0,
"executionTimeMillis" : 1585381,
"totalKeysExamined" : 330494,
"totalDocsExamined" : 330494,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"placed_at" : {
"$exists" : true
}
},
{
"deleted_at" : {
"$eq" : null
}
},
{
"exported_at" : {
"$eq" : null
}
},
{
"failed_export" : {
"$eq" : false
}
}
]
},
获奖计划是:
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"placed_at" : {
"$exists" : true
}
},
{
"deleted_at" : {
"$eq" : null
}
},
{
"exported_at" : {
"$eq" : null
}
},
{
"failed_export" : {
"$eq" : false
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"placed_at" : 1
},
"indexName" : "placed_at_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"placed_at" : [
"[MinKey, MaxKey]"
]
}
}
},
它确实列出了我在其中一个被拒绝的计划中创建的索引。
关于它为什么会遍历数据库中的每条记录的任何想法?这伤害了我们的表现。
我试过暗示正确的记录,这似乎没什么帮助。
答案 0 :(得分:2)
最好不要查询deleted_at: null
,而是创建新的status
字段或isDeleted
字段并配置您的应用服务器以填充该字段。然后,您可以在此字段上创建更有效的索引,以查找所有软删除的文档。
来自Performance Best Practices for MongoDB白皮书:
避免在查询中出现否定。与大多数数据库系统一样,MongoDB不会为缺少值编制索引,而否定条件可能需要扫描所有文档。如果否定是唯一的条件并且没有选择性(例如,查询订单表中99%的订单已完成以识别那些尚未履行的订单),则需要扫描所有记录。