具有null,false和true的查询的复合mongo索引优化

时间:2016-10-01 22:37:59

标签: mongodb

我正在试图找出创建索引的最佳方法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]"
                                    ]
                            }
                    }
            },

它确实列出了我在其中一个被拒绝的计划中创建的索引。

关于它为什么会遍历数据库中的每条记录的任何想法?这伤害了我们的表现。

我试过暗示正确的记录,这似乎没什么帮助。

1 个答案:

答案 0 :(得分:2)

最好不要查询deleted_at: null,而是创建新的status字段或isDeleted字段并配置您的应用服务器以填充该字段。然后,您可以在此字段上创建更有效的索引,以查找所有软删除的文档。

来自Performance Best Practices for MongoDB白皮书:

  

避免在查询中出现否定。与大多数数据库系统一样,MongoDB不会为缺少值编制索引,而否定条件可能需要扫描所有文档。如果否定是唯一的条件并且没有选择性(例如,查询订单表中99%的订单已完成以识别那些尚未履行的订单),则需要扫描所有记录。

相关问题