mongo查询似乎越来越慢

Posted

技术标签:

【中文标题】mongo查询似乎越来越慢【英文标题】:mongo query seems to be getting slower and slower 【发布时间】:2022-01-12 02:23:03 【问题描述】:

我正在使用 spring boot 尝试从 mongo db (4.2) 中检索一组文档。有大约一百万个文档要检索。我正在使用 Paging 并一次获取 100 个文档。


findByCreatedDateLessThanAndStatusInAndFlagNot

CreatedDate 上有一个索引,有 5 种可能的状态(我试图找到其中的 2 个)。当我找到一个文档时,我会使用 MongoTemplate 将标志设置为 true(因此它不会在下一个查询中返回)。我正在设置分页,以便它只获取第 0 页(更新标志,意味着这些文档不会在下一次调用中返回)。

前一千个调用很快,大约一秒钟,但随后它开始变得越来越慢,有些调用需要 20 分钟才能返回结果。任何想法或想法都非常感谢。谢谢

【问题讨论】:

您是否也尝试过索引状态和标志? 我没有。我认为状态只有 5 个可能的值和标志 2,索引对他们来说并不是那么有效。也没有解释第一次通话怎么这么快 【参考方案1】:

后面页面中的这个查询会比集合扫描更糟糕。

根据描述,您的文档包含:


  CreatedDate: ISODate(),
  Status: "one", // of five
  Seen: false

有一个索引

 CreatedDate: 1

您正在运行类似于以下内容的查询:

Collection.find(
     CreateDate:$lte:ISODate(), 
     Status: $in:["one","two"],
     Seen: false
).limit(100)

然后您检索这些文档,并发送(希望是批量)更新以将每个文档的 Seen 标志设置为 true,然后再次运行查询以查找第二批。

假设状态值分布均匀,在 5 个中查找 2 个意味着大约 40% 的数据集,因此要返回 100 万个文档意味着大约有 225 万个文档与日期匹配。

查询如何运行

在第一次运行时,数据库将从最早的值开始扫描索引,将文档加载到内存中,并检查 StatusSeen 字段。

如果文档匹配,则将其添加到结果集中,否则将其丢弃,并加载下一个。

当结果集达到 100 个文档时,查询执行器发送批处理,并终止查询。

假设状态是均匀分布的,这意味着检查 225 个文档以返回前 100 个。

到目前为止一切都很好......但我们还没有完成:

更新后,当请求第二批时,数据库将从最早的值开始扫描索引,将文档加载到内存中,并检查StatusSeen字段。

不匹配,因为Seen 在上一次查询后更新为 true。它将重新检查与日期匹配的前 225 个文档,并且找不到要添加到结果集中的任何内容。之后,它可能需要检查另外 225 个文档才能找到 100 个匹配项。

随着此过程的进行,第 1000 批将需要检查之前检查过的 225,000 个文档,然后检查未检查过的 225 个文档,第 1001 个 225,225 + 225,依此类推。

一次返回 100 万个文档 100 需要 10,000 个批次。最后一批将检查 2,250,000 个文档以返回 100 个。

在某些时候,很可能需要删除一些早期的文件,以便腾出空间来检查后面的文件。当这种情况发生时,从那时起每批所需的时间会有很大的飞跃。

总体而言,整个操作将检查前 225 个文档 10,000 次,第二个 225 个文档 9,999 次等。总计超过 110 亿 个文档检查将已经发生了以 100 个批次返回这 100 万个文档。

如果您使用的计算机每秒可以加载和检查 1,000,000 个文档,则整个操作将需要大约 3 个小时来识别返回的百万个文档,这还不包括网络往返或更新。

如何改进?

CreatedDate: 1, Seen: 1 上创建索引

如果该索引可用,则数据库将能够在索引扫描期间跳过已经看到的文档,因此不需要检查它们。这意味着您只需每批检查 225 个文档,整体操作将返回百万文档,仅检查 2,250,000 个文档,减少约 99.98%。

再改进一点:

CreatedDate: 1, Status: 1, Seen: 1上创建索引

如果该索引可用,则在索引扫描中,数据库也可以跳过状态不正确的文档。这将进一步减少文件审查到1,000,000,即与返回文件的1:1。

【讨论】:

哇,感谢您的详细解释,将添加索引并查看进展情况。 我尝试添加最后一个索引。每个查询大约需要 2 分钟。不知道从哪里开始改进它。 检查explain 看看它在做什么。

以上是关于mongo查询似乎越来越慢的主要内容,如果未能解决你的问题,请参考以下文章

运行查询时,mongo上的聚合函数运行速度非常慢

mongo 杀掉慢的程序killMyRunningOps("12.23.32.21") #####这个是客户端的ip

mongodb查询响应时间慢

Mongo $or 查询范围是在内存中排序吗?

Mongodb 3 查询优化

相同限制的 MySQL SELECT 查询越来越慢