在C#中迭代大型集合:需要很长时间

Bla*_*olf 5 c# iteration collections wpf

我最近开始使用WPF应用程序.我将它连接到BaseX(基于XML)的数据库,并从中检索了大约一百万个条目.我想迭代条目,为每个条目计算一些东西,然后将其写回数据库:

IEnumerable<Result> resultSet = baseXClient.Query("...", "database");
foreach (Result result in resultSet) 
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

问题:从未达到过foreach的内部.Query()方法返回得非常快,但是当到达foreach时,C#似乎对集合进行了SOMETHING,代码不会持续很长时间(至少10分钟,永远不会让它再运行).这里发生了什么?我试图限制检索的项目数量.检索100.000结果时,会发生相同的事情,但代码会在大约10-20秒后继续.检索完整的一百万个结果时,C#似乎永远陷入困境......

有任何想法吗?问候

编辑:为什么会发生这种情况 正如你们中的一些人所指出的,这种行为的原因似乎是查询实际上仅在MoveNext()调用Enumerable中的Enumerator 时进行评估.我的数据库似乎无法一次返回一个值,而是一次返回整个一百万个数据集.我将尝试切换到另一个数据库(Apache Lucene,如果可能的话,因为它具有良好的全文搜索支持)并编辑此帖子以告知您是否更改了任何内容.
PS:是的,我知道有一百万个结果很多.这不是用于实时使用,它只是准备数据的一个步骤.虽然我没想到代码会在几秒钟内运行,但我仍然对数据库中的性能不佳感到惊讶.

编辑:解决方案因此我将XML数据库迁移到Apache Lucine.奇迹般有效!当然Lucine是一个基于文本的数据库,并不适用于每个用例,但对我来说它创造了奇迹.可以在几秒钟内迭代超过一百万个条目,每个循环获取一个条目 - 工作得非常好!

小智 5

让我猜一下 - 你在创建rsultSet时没有加载数据,但是当它第一次被访问(延迟执行),并加载一百万个条目时,你只需要花费大量的时间将它们反序列化到内存中.

欢迎使用XML数据库的低效率.


Ale*_*kov 3

一百万个东西就很多了...因此任何获取这么多项目的操作预计都会花费大量时间。看起来您使用的库不会推迟检索项目,直到绝对必要为止 - 因此您会看到将所有项目隐藏在“foreach”语句后面的影响。

会发生什么:

“foreach”不是单个操作,而是对 IEnumerable 和 IEnumerator 的多次调用:IEnumerable.GetEnumerator、重复调用 IEnumerator.MoveNext。

第一次调用GetEnumerator可以通过延迟执行(编写 LINQ 查询的最常见方式)或立即执行(这似乎是您的集合的情况)来实现。

即使您只要求单个项目或每次调用只能获取单个项目,对 MoveNext 的调用也可能会触发整个查询的立即执行。即,大多数 LINQ 查询仅从迭代器获取下一项。