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

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


findByCreatedDateLessThanAndStatusInAndFlagNot

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

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

【问题讨论】:

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

标签: mongodb spring-data-jpa spring-data


【解决方案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 看看它在做什么。
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 2016-03-05
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
相关资源
最近更新 更多