我正在使用带有 Spring Data 的 Spring Boot 2 和本地 Mongodb 3.4。 我目前有一个包含约 20 万个文档的集合,通过 Spring 的注释正确索引。
我制作了一个聚合管道(见本文底部),需要大约2000ms才能完成:Python、Studio3T、Spring Boot 单元测试。
当我在应用程序的部署实例(bootJar)上正常运行相同的查询时,需要8000ms,这对于我的用例来说是 Not Acceptable ,而且也是很奇怪。
数据库日志报告在所有情况下的查询时间约为 300 毫秒,因此数据库性能良好。
找出发生这种情况的原因非常有趣,因为正常部署和单元测试期间的代码完全相同(也使用相同的参数),因此在性能上应该具有可比性。
我的猜测是部署和测试之间的配置有所不同。我在两个环境中都使用默认设置(没有针对 mongo 的特定 bean 声明,只是 Autowiring MongoOperations
并享受“启动魔法”)。
以下是一些示例:
文档如下所示:
{
"_id" : ObjectId("5b4f76696d370f30d401f246"),
"description" : "IoT420",
"timestamp" : NumberLong(1530286316),
"sensor" : "Temperature",
"value" : 30.02,
"class" : "net.derp.iot.piws.entities.dto.MongoMeasurementRepr"
}
聚合管道:
Aggregation aggregation = newAggregation(
match( where( "description" ).is( filterDescription ) ),
match( where( "sensor" ).is( sensorName ) ),
match( where( "timestamp" ).gte( tsFrom ).lte( tsTo ) ),
sort( Sort.Direction.ASC, "timestamp" ));
此聚合返回大约 120k 文档。
我使用System.nanoTime()
来测量时间。
更新:删除runtime('org.springframework.boot:spring-boot-devtools')
后,时间下降到5000ms,这仍然比测试用例慢。我怀疑某种“验证”在测试过程中被禁用。
最佳答案
我浏览了您的查询,发现您在两个比赛阶段后给出了时间戳标准。理想情况下,日期条件应该放在 mongo 查询中的第一位,因为它可以缩小下一阶段要扫描的文档数量。
所以你的聚合查询应该是
Aggregation aggregation = newAggregation(
match( where( "timestamp" ).gte( tsFrom ).lte( tsTo ) ),
match( where( "description" ).is( filterDescription ) ),
match( where( "sensor" ).is( sensorName ) ),
sort( Sort.Direction.ASC, "timestamp" ));
关于spring - Mongodb 聚合仅在 Spring Data 上缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51410704/