【问题标题】:MongoDB query (range filter + sort) performance tuningMongoDB查询(范围过滤+排序)性能调优
【发布时间】:2019-03-21 11:35:11
【问题描述】:

我有一个 Mongo 集合,其中包含数百万个具有以下格式的文档:

{
    "_id" : ObjectId("5ac37fa989e00723fc4c7746"),
    "group-number" : NumberLong(128125089),
    "date" : ISODate("2018-04-03T13:20:41.193Z")
}

我想检索按“group-number”排序的 2 个日期(“date”)之间的文档。所以,我正在执行这种查询:

db.getCollection('group').find({date:{$gt:new Date(1491372960000),$lt:new Date(1553152560000)}}).sort({"group-number":1})

根据https://blog.mlab.com/2012/06/cardinal-ins/ 看来,MongoDB 在不按 equivalent 值但使用 range 值(如我的情况)查询时,最好有一个索引以相反的顺序(首先是排序的字段/然后是过滤的字段)。 事实上,我使用索引db.group.createIndex({"group-number":1,"date":1}); 获得了最好的结果。但是仍然需要很长时间;在相同情况下超过 40 秒。

根据explain()的结果,确实是在使用上面的索引。

"winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "$and" : [ 
                    {
                        "date" : {
                            "$lt" : ISODate("2019-03-21T07:16:00.000Z")
                        }
                    }, 
                    {
                        "date" : {
                            "$gt" : ISODate("2017-04-05T06:16:00.000Z")
                        }
                    }
                ]
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "group-number" : 1.0,
                    "date" : 1.0
                },
                "indexName" : "group-number_1_date_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "group-number" : [],
                    "date" : []
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "group-number" : [ 
                        "[MinKey, MaxKey]"
                    ],
                    "date" : [ 
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        }

如何提高性能?我一定是错过了什么……

【问题讨论】:

  • 嘿!你弄明白了吗?
  • 不,我终于放弃了。现在我提取按“日期”排序的数据,因此我还必须调整处理数据的过程。
  • 您是否考虑过 ETL 到一些列式存储而不是查询 mongodb?

标签: mongodb mongodb-indexes


【解决方案1】:

我会以相反的方式建立一个索引:db.createIndex({date: 1, 'group-number': 1})。仅仅因为您实际上是通过date 字段进行查询,所以它应该在复合索引中排在第一位。您仅使用 group-number 进行排序。这样一来,WiredTiger 就更容易在 BTree 中找到需要的文档。

【讨论】:

  • 反向索引是我最初的表现更差的索引。此外,当两个索引都可用时 ({"group-number":1,"date":1} & {"date":1,"group-number":1}) MongoDB 仍然选择 "group-number_1_date_1" 索引如上面的 explain() 结果所示。
  • @Kuikiker 很有趣。字段group-number的分布是什么?它有多少独特的价值?
  • 我无法得到确切的数字,但从 1 到 158000000 有超过 1 亿个不同的“组号”(两者之间有一些差距)。但在我查询的集合中,“组号”不是唯一的,每个“组号”可以有多个条目
  • 取自:docs.mongodb.com/manual/tutorial/sort-results-with-indexes 这似乎是我的问题。 “索引可以支持对索引键模式的非前缀子集的排序操作。为此,查询必须在排序键之前的所有前缀键上包含相等条件。如果查询未指定相等条件在排序规范之前或与排序规范重叠的索引前缀,该操作将无法有效地使用索引"
猜你喜欢
  • 1970-01-01
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2015-08-18
相关资源
最近更新 更多