解释 MongoDB 日志输出

Posted

技术标签:

【中文标题】解释 MongoDB 日志输出【英文标题】:Explain MongoDB log output 【发布时间】:2017-09-09 07:01:09 【问题描述】:

我有带有索引timestamp_1, timestamp_2 and user_id 字段的位置集合。执行查询时(您可以在以下日志中看到),然后查询大约需要 3 分钟(175670 毫秒)。我不知道为什么会这样!! 我附上了以下 MongoDB-Log。 任何人都可以根据日志向我解释一下,我该如何优化它?

2017-04-12T17:04:33.759+0000 I COMMAND [conn167] 查询 位置集合查询: orderby: timestamp_1:1 ,$query: $and: [ timestamp_1: $lte: 1492016294486.0 , timestamp_2: $gte: 1491993563400.0 , user_id: "jkfjlsjfflki-14asddsd" planSummary: IXSCAN user_id: 1 , IXSCAN user_id: 1 ntoreturn:1000 ntoskip:0 keysExamined:27254 docsExamined:27254 hasSortStage:1 cursorExhausted:1 keyUpdates:0 writeConflicts:0 numYields:3350 nreturned:67 reslen:176574 locks: Global: 获取计数: r:6702 ,数据库:获取计数: r:3351 , 集合: acquireCount: r: 3351 175670ms

还有一个问题:我正在创建自己的“_id”字段值,所以这种方式有什么缺点吗??我只创建字符串值并期望 mongoDb 索引它没有任何问题。

2017-04-12T17:04:41.979+0000 我命令 [conn150] 查询 db.users 查询:orderby:_id:1,$查询:_id: "USR-dfhsddf-14905426shfkjdhf" plan总结:IDHACK ntoreturn:1 ntoskip:0 keysExamined:1 docsExamined:1 idhack:1 cursorExhausted:1 keyUpdates:0 writeConflicts:0 numYields:0 nreturned:1 reslen:1291 锁:全局:acquireCount:r:2,数据库:acquireCount: r: 1 ,集合: acquireCount: r: 1 2627ms

提前致谢!

【问题讨论】:

【参考方案1】:

先回答第二个问题 - _id 可以使用自己的值。 MongoDB 将正确索引它。这样做的结果是现在您的应用程序有责任确保没有重复。

默认的 MonogDB ObjectId 类型还在值中包含时间戳。这意味着当 _id 字段是 ObjectId 时,按插入顺序(或技术上创建 ObjectId 时的时间戳)返回结果。

关于日志输出,查询性能输出值来自Database Profiler。您可以在https://docs.mongodb.com/manual/reference/database-profiler/ 看到值列表。

查询性能非常有用的工具是explain()、https://docs.mongodb.com/manual/reference/method/cursor.explain/ 和https://docs.mongodb.com/manual/reference/explain-results/。您必须在自己的系统上测试查询的执行方式。

您的集合中的各个字段似乎具有三个不同的索引:timestamp_1timestamp_2user_id

查询正在比较三个字段:

timestamp_1 小于一个值 timestamp_2 大于一个值 user_id 等于一个值

您还可以通过输出中的timestamp_1 字段进行排序。

planSummary: IXSCAN user_id: 1 , IXSCAN user_id: 1 表示查询计划器正在为查询选择user_id 上的索引,然后再次选择user_id 上的索引以用于排序,这不是您真正想要排序的字段在。如需参考,请参阅https://groups.google.com/forum/#!topic/mongodb-user/nQlmVdODo-M。

keysExamined:27254 表示索引扫描检查了索引中的 27254 个键。 docsExamined:27254 表示 MongoDB 从磁盘中提取了 27245 个文档来检查内容。 nreturned:67 声明查询结果返回了 67 个文档。扫描user_id 索引,找到 27254 个匹配项,然后从集合中检索每个文档。解析这些文档并比较 timestamp* 字段,并返回 67 条匹配记录。未使用 timestamp_1timestamp_2 索引。

MongoDB 将索引存储为 B-TREE,并且允许复合索引 (https://docs.mongodb.com/manual/indexes/)。您可以测试创建新的索引组合,分析结果,并查看哪个最适合您的应用程序。包含所有三个字段的复合索引将允许查询仅使用索引分析所有查询字段(user_idtimestamp_1timestamp_2),这应该会减少 MongoDB 需要读取的文档数量的磁盘。一个可能的例子是:

db.collection.createIndex(user_id:1, timestamp_1:1, timestamp_2:-1)

此索引将允许 Mongo 查询计划器匹配 user_id 字段,然后找到 timestamp_1 小于该值的结果,然后找到更多 timestamp_2 大于其值的结果。因为timestamp_1列在timestamp_2之前,匹配的记录已经排序,这也可能让MongoDB跳过排序阶段。您需要在自己的系统上对此进行测试,以验证其性能是否更好。根据集合中文档的基数,您可以尝试将时间戳字段放在 user_id 字段之前。

【讨论】:

以上是关于解释 MongoDB 日志输出的主要内容,如果未能解决你的问题,请参考以下文章

配置MongoDB配置文件详细配置

Logstash 之 Tomcat日志收集

mongodb config配置

.NetCore 日志在 GCP Stackdriver 中输出错误的严重性

玩转mongodb:通过log4jmongo来实现分布式系统的日志统一管理

kafka利用log4j输出日志到哪里