【问题标题】:optimize mongo query to get max date in a very short time优化 mongo 查询以在很短的时间内获得最大日期
【发布时间】:2022-06-14 17:51:55
【问题描述】:

我正在使用下面的查询来获取名为 KPI 的集合中的最大日期(名为 extractDate 的字段),因为我只对字段 extractDate 感兴趣:

@Override
public Mono<DBObject> getLastExtractionDate(MatchOperation matchOperation,ProjectionOperation projectionOperation) {
    return Mono.from(mongoTemplate.aggregate(
            newAggregation(
                    matchOperation,
                    projectionOperation,
                    group().max(EXTRACTION_DATE).as("result"),
                    project().andExclude("_id")
            ),
            "kpi",
            DBObject.class
    ));
}

正如您在上面看到的,我需要首先使用匹配操作(matchOperation)过滤结果,然后我正在执行投影操作以仅提取字段“extractionDate”的最大值并将其重命名为结果。

但是这个查询花费了很多时间(有时超过20秒),因为我有大量的数据,我已经在字段extractionDate上添加了一个索引但是我没有收获很多,所以我正在寻找一种尽可能快地掌握它的方法。

更新:

我们在集合 kpi 中拥有的文档数:42.8m 个文档

正在执行的查询:

Streaming aggregation: [{ "$match" : { "type" : { "$in" : ["INACTIVE_SITE", "DEVICE_NOT_BILLED", "NOT_REPLYING_POLLING", "MISSING_KEY_TECH_INFO", "MISSING_SITE", "ACTIVE_CIRCUITS_INACTIVE_RESOURCES", "INCONSISTENT_STATUS_VALUES"]}}}, { "$project" : { "extractionDate" : 1, "_id" : 0}}, { "$group" : { "_id" : null, "result" : { "$max" : "$extractionDate"}}}, { "$project" : { "_id" : 0}}] in collection kpi

解释计划:

集合 KPI 中的文档示例:

最后是这个集合中已经存在的索引:

【问题讨论】:

  • 性能提示:(1)匹配操作查询中使用的字段可以使用索引进行高效过滤。 (2) 小组赛前的投影操作可能不需要,除非你正在执行一些计算来得到那个日期。

标签: java spring mongodb spring-data-mongodb mongotemplate


【解决方案1】:

索引调整将更多地取决于$match 表达式中的属性。您应该能够在 mongosh 中运行查询并获得解释计划以确定您的查询是否正在扫描集合。

要考虑的其他事项是集合的大小与服务器的工作集的大小。

也许可以使用$match 表达式和explain plan 更新您的问题,也许还可以使用当前的索引定义集,我们可以改进索引策略。

最后,什么是相当主观的?您是在查询数百万或数十亿的文档吗?平均文档大小是多少?

【讨论】:

  • 感谢您提供详细信息,我刚刚按照要求更新了我的问题
【解决方案2】:

由于以前使用这种方法的答案,我能够优化请求:

@Override
public Mono<DBObject> getLastExtractionDate(MatchOperation matchOperation,ProjectionOperation projectionOperation) {
    return Mono.from(mongoTemplate.aggregate(
            newAggregation(
                    matchOperation,
                    sort(Sort.Direction.DESC,EXTRACTION_DATE),
                    limit(1),
                    projectionOperation
            ),
            "kpi",
            DBObject.class
    ));
}

我还必须在提取日期和类型(我在 matchOperation 中的字段)上创建一个复合索引,如下所示:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2023-03-18
    • 2014-10-17
    • 2010-09-22
    • 1970-01-01
    相关资源
    最近更新 更多