spring-data-mongodb - 使用 Spring Data MongoDb v2.x 时如何访问 explain() 方法和 executionStats?
问题描述
是时候问问社区了。我无法在任何地方找到答案。
我想创建一个通用方法,可以跟踪我所有的存储库查询,并在查询未优化(也就是缺少索引)时警告我。
使用 Spring Data MongoDb v2.x 及更高版本以及引入 Document API,我无法弄清楚如何访问 DBCursor 和 explain() 方法。
旧的方法是这样做: https ://enesaltinkaya.com/java/how-to-explain-a-mongodb-query-in-spring/
对此的任何建议表示赞赏。
解决方案
我知道这是一个老问题,但想从我在使用 Java Mongo API 驱动程序 v2.X 的 cosmos Db 项目的容量规划中提出的类似要求中提供意见。
总结Enes Altınkaya 的博文。使用@autowired
MongoTemplate,我们使用runCommand通过传递 Document 对象来执行服务器端数据库查询。获得解释输出,我们将 Query 或 Aggregate 对象解析为新的 Document 对象并添加条目{"executionStats": true}
(或{"executionStatistics": true}
用于 cosmos Db)。然后使用“解释”作为属性将其包装在另一个文档中。
例如:
查询:
public static Document documentRequestStatsQuery(MongoTemplate mongoTemplate,
Query query, String collectionName) {
Document queryDocument = new Document();
queryDocument.put("find", collectionName);
queryDocument.put("filter", query.getQueryObject());
queryDocument.put("sort", query.getSortObject());
queryDocument.put("skip", query.getSkip());
queryDocument.put("limit", query.getLimit());
queryDocument.put("executionStatistics", true);
Document command = new Document();
command.put("explain", queryDocument);
Document explainResult = mongoTemplate.getDb().runCommand(command);
return explainResult;
}
聚合:
public static Document documentRequestStatsAggregate(MongoTemplate mongoTemplate,
Aggregation aggregate, String collection) {
Document explainAggDocument = Document.parse(aggregate.toString());
explainAggDocument.put("aggregate", collection);
explainAggDocument.put("executionStatistics", true);
Document command = new Document();
command.put("explain", explainAggDocument);
Document explainResult = mongoTemplate.getDb().runCommand(command);
return explainResult;
}
对于实际监控,由于 Service 和 Repository 类是 MongoTemplate 抽象,我们可以使用 Aspects 在应用程序运行时捕获查询/聚合执行细节。
例如:
@Aspect
@Component
@Slf4j
public class RequestStats {
@Autowired
MongoTemplate mongoTemplate;
@After("execution(* org.springframework.data.mongodb.core.MongoTemplate.aggregate(..))")
public void logTemplateAggregate(JoinPoint joinPoint) {
Object[] signatureArgs = joinPoint.getArgs();
Aggregation aggregate = (Aggregation) signatureArgs[0];
String collectionName = (String) signatureArgs[1];
Document explainAggDocument = Document.parse(aggregate.toString());
explainAggDocument.put("aggregate", collectionName);
explainAggDocument.put("executionStatistics", true);
Document dbCommand = new Document();
dbCommand.put("explain", explainAggDocument);
Document explainResult = mongoTemplate.getDb().runCommand(dbCommand);
log.info(explainResult.toJson());
}
}
每次执行后输出如下内容:
{
"queryMetrics": {
"retrievedDocumentCount": 101,
"retrievedDocumentSizeBytes": 202214,
"outputDocumentCount": 101,
"outputDocumentSizeBytes": 27800,
"indexHitRatio": 1.0,
"totalQueryExecutionTimeMS": 15.85,
"queryPreparationTimes": {
"queryCompilationTimeMS": 0.21,
"logicalPlanBuildTimeMS": 0.5,
"physicalPlanBuildTimeMS": 0.58,
"queryOptimizationTimeMS": 0.1
},
"indexLookupTimeMS": 10.43,
"documentLoadTimeMS": 0.93,
"vmExecutionTimeMS": 13.6,
"runtimeExecutionTimes": {
"queryEngineExecutionTimeMS": 1.56,
"systemFunctionExecutionTimeMS": 1.36,
"userDefinedFunctionExecutionTimeMS": 0
},
"documentWriteTimeMS": 0.68
}
// ...
我通常将其记录到另一个集合中或写入文件。
推荐阅读
- java - 如何使用 TCP 连接到服务器
- python - datetime.now returns wrong time if timezone changed after running interpreter
- mysql - Compare MySQL Timestamp with NodeJS
- android - 如果我点击 ImageView1 中的一个位置,则在 ImageView2 上以与 ImageView1 相同的坐标绘制一个圆圈,反之亦然
- c# - 使用 system.net.webclient 时如何解决“远程服务器返回错误 401 未授权”?
- python - Python text processing
- javascript - 我的网站上出现了额外的空白 div 层,我不知道如何删除它。
- python-3.x - Python DRY 类初始化
- c - Arduino C 多维数组切换
- postgresql - How to allow a user to see a subset of a table or view