mongodb 聚合$查找太慢

azpvetkf  于 2022-11-03  发布在  Go
关注(0)|答案(1)|浏览(195)

第1阶段:$Match

{
  delFlg: false
}

第2阶段:$lookup

{
  from: "parkings",
  localField: "parking_id",
  foreignField: "_id",
  as: "parking",
}

使用2个IDX(ID & parking_ID)。在MongoDB /Linux/ Compass中的解释计划约为9000 ms。在本地MongoDB服务器中的解释计划约为1400 ms。
有什么问题吗?为什么我们的生产服务器运行得这么慢?
完整解释计划

Explain Plan
Query Performance Summary
Documents returned:
71184
Actual query execution time (ms):
8763
Query used the following indexes:
2

_id_

delFlg_1
explainVersion
"1"

stages
Array

serverInfo
Object

serverParameters
Object

command
Object
ok
1

$clusterTime
Object
operationTime
Timestamp({ t: 1666074389, i: 3 })

使用MongoDB 5.0.5版本本地MongoDB 6.0.2版本

bihw5rsg

bihw5rsg1#

不幸的是,提供的explain输出大部分被截断了(例如ArrayObject隐藏了大部分重要信息)。即使没有这些,我们也应该可以做出一些有意义的观察。
和往常一样,我建议从更清晰地定义你的最终目标开始。什么被认为是“* 如此缓慢 *”,操作需要多快才能返回,以便为你的用例所接受?如下所述,我怀疑目前的模式是否有很大的改进空间。如果你正在寻找本质上是几个数量级的改进,你可能需要完全重新考虑这种方法。
让我们考虑一下该操作的作用:

  • 数据库转到值为false{ delFlg: 1 }索引中得一个条目.
  • 然后转到FETCH,从集合中找到完整的文档。
  • 根据parking_id字段的值,它在parkings集合上执行{ _id: 1 }索引的IXSCAN。如果发现匹配的索引条目,则数据库将从其他集合中FETCH整个文档,并将其添加到正在生成的新parking数组字段中。
  • 然后,整个过程重复 * 71,183次 *。

使用8763ms作为持续时间,这意味着数据库每毫秒执行上述工作的每个完整迭代超过8次(8.12 ~= 71184 (iters) / 8763 (ms))。我认为这听起来很合理,但不太可能是您可以有意义地改进的地方。扩展运行数据库的硬件可能会提供一些增量改进,但是它通常成本很高,不可伸缩,如果您正在寻找更实质性的改进,那么它可能不值得。
您在问题中还提到了两个不同的时间和数据库版本。如果我理解正确的话,您提到(explain)操作在5.0版本上需要大约9秒,在6.0版本上大约需要1.4秒。虽然这里提供的信息太少,无法确定,其中一个原因可能与6.0版本中引入的$lookup的改进有关。实际上,根据他们的7 Big Reasons to Upgrade to MongoDB 6.0 article,他们声明如下:
$lookup的性能也得到了提升,例如,如果外键上有索引,并且匹配了少量文档,$lookup可以比以前快5到10倍得到结果。
这似乎与你的情况和观察非常直接地匹配。
除了升级之外,还有什么可以提高性能呢?如果源集合中的许多/大多数文档都有{ delFlg: false },那么您可能希望去掉{ delFlg: 1 }索引。当检索的结果相对于集合中数据的整体大小很小时,索引会提供一些好处。但是随着百分比的增加,扫描大部分索引 * 加上 * 随机快速获取所有数据的开销比直接扫描整个集合的效率要低。注解中提到invoices集合包含70 k个文档,因此delFlg上的这个 predicate 似乎根本没有删除任何结果。
另一个非常突出的问题是评论中的这句话“parkings contains 16 documents"。是否应该将这16个文档中的信息直接移到parkings文档中?如果这两个文档经常一起访问,并且parkings信息不经常更改,那么将两者结合将减少大量开销并将进一步提高性能。
关于explain,还有两个值得记住的组件:

  • 此命令 * 不 * 考虑将结果实际传输到客户端的网络时间。根据文档的大小和环境的物理拓扑,此网络时间可能会给操作增加另一个有意义的延迟。请确保客户端确实需要正在发送的所有数据。
  • 根据详细程度,explain将测量从运行操作到完成所需的时间。由于在聚合管道中没有阻塞阶段,因此我们希望在更短的时间内将初始文档批返回到客户端。对于5.0,除网络连接外,该时间可能约为12ms(约为(101 docs / 71184 ) * 8763)。

相关问题