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 万个文档与日期匹配。
查询如何运行
在第一次运行时,数据库将从最早的值开始扫描索引,将文档加载到内存中,并检查 Status
和 Seen
字段。
如果文档匹配,则将其添加到结果集中,否则将其丢弃,并加载下一个。
当结果集达到 100 个文档时,查询执行器发送批处理,并终止查询。
假设状态是均匀分布的,这意味着检查 225 个文档以返回前 100 个。
到目前为止一切都很好......但我们还没有完成:
更新后,当请求第二批时,数据库将从最早的值开始扫描索引,将文档加载到内存中,并检查Status
和Seen
字段。
不匹配,因为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查询似乎越来越慢的主要内容,如果未能解决你的问题,请参考以下文章