【问题标题】:Index on array element attribute extremely slow数组元素属性上的索引非常慢
【发布时间】:2022-10-24 00:19:44
【问题描述】:

我是 mongodb 的新手,但对数据库并不陌生。我创建了一个如下所示的文档集合:

{_id: ObjectId('5e0d86e06a24490c4041​​bd7e') , , 匹配[{ _id: ObjectId(5e0c35606a24490c4041​​bd71), ts:1234456, , ,}] }

所以文档上有一个对象列表,在列表中可能有许多具有相同 _id 字段的对象。我在这个集合中有一些文档,我的查询在选定的 match._id 上进行选择非常慢。我的意思是不自然的慢。

查询很简单: {match: {$elemMatch: {_id:match._id }}} 并从字面上将系统挂起 15 秒,返回总共 25 个匹配文档中的 15 个!

我在集合上放了一个索引,如下所示: collection.createIndex({"match._id" : 1}) 但这没有帮助。

Explain 说执行时间为 0,并说它正在使用索引,但仍需要 15 秒或更长时间才能完成。

我在 nodejs 和 compass 中遇到了同样的缓慢。

解释输出: {"explainVersion":"1","queryPlanner":{"namespace":"hp-test-39282b3a-9c0f-4e1f-b953-0a14e00ec2ef.lead","indexFilterSet":false,"parsedQuery":{"match" :{"$elemMatch":{"_id":{"$eq":"5e0c3560e5a9e0cbd994fa52"}}}},"maxIndexedOrSolutionsReached":false,"maxIndexedAndSolutionsReached":false,"maxScansToExplodeReached":false,"winningPlan":{"阶段":"FETCH","filter":{"match":{"$elemMatch":{"_id":{"$eq":"5e0c3560e5a9e0cbd994fa52"}}}},"inputStage":{"stage": "IXSCAN","keyPattern":{"match._id":1},"indexName":"match._id_1","isMultiKey":true,"multiKeyPaths":{"match._id":["match"] },"isUnique":false,"isSparse":false,"isPartial":false,"indexVersion":2,"direction":"forward","indexBounds":{"match._id":["[ObjectId( '5e0c3560e5a9e0cbd994fa52'), ObjectId('5e0c3560e5a9e0cbd994fa52')]"]}}},"rejectedPlans":[]},"executionStats":{"executionSuccess":true,"nReturned":15,"executionTimeMillis":0," totalKeysExamined":15,"totalDocsExamined":15,"executionStages":{"stage":"FETCH","filter":{"match":{"$elemMatch":{"_id":{"$eq": "5e 0c3560e5a9e0cbd994fa52"}}}},"nReturned":15,"executionTimeMillisEstimate":0,"works":16,"advanced":15,"needTime":0,"needYield":0,"saveState":0," restoreState":0,"isEOF":1,"docsExamined":15,"alreadyHasObj":0,"inputStage":{"stage":"IXSCAN","nReturned":15,"executionTimeMillisEstimate":0,"works ":16,"advanced":15,"needTime":0,"needYield":0,"saveState":0,"restoreState":0,"isEOF":1,"keyPattern":{"match._id" :1},"indexName":"match._id_1","isMultiKey":true,"multiKeyPaths":{"match._id":["match"]},"isUnique":false,"isSparse":false, "isPartial":false,"indexVersion":2,"direction":"forward","indexBounds":{"match._id":["[ObjectId('5e0c3560e5a9e0cbd994fa52'), ObjectId('5e0c3560e5a9e0cbd994fa52')]"] },"keysExamined":15,"seeks":1,"dupsTested":15,"dupsDropped":0}},"allPlansExecution":[]},"command":{"find":"lead"," filter":{"match":{"$elemMatch":{"_id":"5e0c3560e5a9e0cbd994fa52"}}},"skip":0,"limit":0,"maxTimeMS":60000,"$db":" hp-test-39282b3a-9c0f-4e1f-b953-0a14e00ec2ef"},"serverInfo":{"host":"Dans-MacBook-Pro.lo cal","port":27017,"version":"5.0.9","gitVersion":"6f7dae919422dcd7f4892c10ff20cdc721ad00e6"},"serverParameters":{"internalQueryFacetBufferSizeBytes":104857600,"internalQueryFacetMaxOutputDocSizeBytes":104857600,"internalLookupStageIntermediateDocumentMaxSizeBytes":104857600 "internalDocumentSourceGroupMaxMemoryBytes":104857600,"internalQueryMaxBlockingSortMemoryUsageBytes":104857600,"internalQueryProhibitBlockingMergeOnMongoS":0,"internalQueryMaxAddToSetBytes":104857600,"internalDocumentSourceSetWindowFieldsMaxMemoryBytes":104857600},"ok":1}

【问题讨论】:

  • 请分享解释输出
  • 在上面添加。抱歉,我不知道如何更好地格式化

标签: arrays mongodb mongodb-query


【解决方案1】:

explain 输出确认所解释的操作非常有效。我们特别看到:

  • 与紧indexBounds 一起使用的预期索引
  • 高效访问数据 (totalKeysExamined == totalDocsExamined == nReturned)
  • 没有有意义的持续时间("executionTimeMillis":0 这意味着数据库执行该操作花费的时间少于0.5ms

因此,您在该特定操作中遇到的缓慢与计划本身的效率无关。这并不总是完全排除数据库(或其底层服务器)是缓慢的根源,但它通常是一个非常强烈的指标,表明问题出在其他地方或有多种因素在起作用。

我建议以下作为潜在的后续步骤:

  • 检查mongod日志文件(你可以通过运行db.adminCmd("getCmdLineOpts") via the shell connected to the instance). By default any operation slower than 100ms`来确认它的位置被捕获。这将有多种帮助:
    • 如果有日志条目(具有有意义的持续时间),则它确认在数据库处理操作时引入了缓慢。它还可以提供一些有用的提示,说明为什么会出现这种情况(例如等待锁或服务器资源,例如存储)。
    • 如果关联条目不能被发现,那么这将是更强有力的证据,表明我们在错误的地方寻找缓慢的根源。
  • 是你为explain收集的操作精确的应用程序和 Compass 观察到的速度很慢?您是否连接到相同的服务器和命名空间?解释的操作是否以某种方式简化,例如包含排序、投影、整理等的原始操作?
    • 作为结合这两者的相关示例,我注意到有skiplimit 参数应用于看似在笔记本电脑上运行的mongod 上解释的命令。这些参数在运行应用程序时是否非零,并且应用程序是否针对具有更大数据集的不同数据库运行?
  • explain 命令不包括一切一个应用程序会。值得注意的是,通过网络发送结果所需的实际时间。如果您有特别大的文件,这可能是一个因素,尽管在这种特殊情况下它似乎不太可能是罪魁祸首。
  • 您如何准确测量完整执行时间?它是否可能包括连接到数据库的时间?在这种情况下,您提到 Compass 本身也表现出缓慢,因此可以排除大部分情况。
  • 托管数据库的服务器上还运行着什么?是否涉及容器或虚拟机?数据库或底层服务器是否会因并发而发生资源争用?

两个额外的小旁白:

  • 一个集合中总共 25 个文档非常小。我希望即使是最小的硬件也能够在没有索引的情况下处理这样的请求,除非有一些复杂的因素。
  • 假设match 始终是一个数组,那么$elemMatch 运算符对于这个特定的查询并不是绝对必要的。您可以阅读更多关于 here 的信息。我不希望这会对您的情况产生性能影响。

【讨论】:

    猜你喜欢
    • 2015-02-23
    • 1970-01-01
    • 2021-11-18
    • 2011-10-08
    • 1970-01-01
    • 2016-11-10
    • 2012-09-15
    • 2013-07-31
    相关资源
    最近更新 更多