Mongodb 聚合仅在 Spring 数据上缓慢
Mongodb aggregation is slow only on Spring Data
我正在使用 Spring Boot 2 与 Spring 数据和本地 Mongodb 3.4。
我目前有一个包含 ~200k 文档的集合,通过 Spring 的注释正确索引。
我制作了一个聚合管道(见此 post 的底部),大约需要 2000 毫秒 完成:Python,Studio3T , Spring 引导单元测试.
当我 运行 通常在我的应用程序 (bootJar) 的 已部署实例上执行完全相同的查询时,需要 8000 毫秒 这对我的用例来说是不可接受的,而且也很奇怪。
数据库日志报告的查询时间在所有情况下均为 ~300 毫秒,因此数据库运行良好。
找出发生这种情况的原因非常有趣,因为正常部署和单元测试期间的代码完全相同(也使用相同的参数),因此在性能上应该具有可比性。
我的猜测是部署和测试之间的配置不同。我在两种环境中都使用默认设置(mongo 没有特定的 bean 声明,只是自动装配 MongoOperations
并享受 "Boot magic")。
以下是一些示例:
文档如下所示:
{
"_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" ));
此聚合 returns 大约 120k 个文档。
我用System.nanoTime()
来衡量时间。
更新:删除runtime('org.springframework.boot:spring-boot-devtools')
后,时间下降到5000ms,仍然比测试用例慢。我怀疑某种 "validation" 在测试期间被禁用。
我查看了您的查询,发现您在两个匹配阶段后给出了时间戳标准。理想情况下,日期条件应该在 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" ));
在 linux 服务器(使用不同的数据库)上部署相同的 jar 后,一切看起来都很正常(查询时间约 2000 毫秒)。我猜我的环境或类似的配置有冲突..
我正在使用 Spring Boot 2 与 Spring 数据和本地 Mongodb 3.4。 我目前有一个包含 ~200k 文档的集合,通过 Spring 的注释正确索引。
我制作了一个聚合管道(见此 post 的底部),大约需要 2000 毫秒 完成:Python,Studio3T , Spring 引导单元测试.
当我 运行 通常在我的应用程序 (bootJar) 的 已部署实例上执行完全相同的查询时,需要 8000 毫秒 这对我的用例来说是不可接受的,而且也很奇怪。
数据库日志报告的查询时间在所有情况下均为 ~300 毫秒,因此数据库运行良好。
找出发生这种情况的原因非常有趣,因为正常部署和单元测试期间的代码完全相同(也使用相同的参数),因此在性能上应该具有可比性。
我的猜测是部署和测试之间的配置不同。我在两种环境中都使用默认设置(mongo 没有特定的 bean 声明,只是自动装配 MongoOperations
并享受 "Boot magic")。
以下是一些示例:
文档如下所示:
{
"_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" ));
此聚合 returns 大约 120k 个文档。
我用System.nanoTime()
来衡量时间。
更新:删除runtime('org.springframework.boot:spring-boot-devtools')
后,时间下降到5000ms,仍然比测试用例慢。我怀疑某种 "validation" 在测试期间被禁用。
我查看了您的查询,发现您在两个匹配阶段后给出了时间戳标准。理想情况下,日期条件应该在 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" ));
在 linux 服务器(使用不同的数据库)上部署相同的 jar 后,一切看起来都很正常(查询时间约 2000 毫秒)。我猜我的环境或类似的配置有冲突..