2011-09-06 148 views
3

我是Linq的粉丝,对于打字,清晰和简洁,我很感兴趣。但是我发现,与旧的数据视图相比,搜索匹配记录的速度非常慢,大约是2000倍!Linq对象与数据视图相比非常缓慢

我正在写一个应用程序来备份大量文件 - 500,000个文件和500 gb的数据。我在备份集中创建了一个文件清单,并将目录中的文件与清单中的文件进行比较,以记录已备份的内容。这样我就知道哪些文件已经更改,因此需要复制。

缓慢步骤是这样的一种:

var matchingMEs = from m in manifest where m.FullName == fi.FullName select m;

其中manifest = List<ManifestEntry>ManifestEntry是一个相对简单POCO。

整体表现为每秒17-18个记录。

当我使用一个数据视图:

DataView vueManifest = new DataView(dt, "", "FullName", DataViewRowState.CurrentRows);

接在回路中找到匹配的清单条目用.FindRows:

matchingMEs = vueManifest.FindRows(fi.FullName);

...然后我得到每秒大约35,000个文件吞吐量!

这是正常的吗?我不能相信Linq会有这样的代价。 Linq还是物体会让事情变得缓慢?

(顺便说一句,我尝试使用一个DictionarySortedList还有List<ManifestEntries>,他们都给出了一个关于同样的结果。)

+0

如果您使用字典获得相同的错误结果,我假设您正在初始化它不正确。请显示相应的代码。另外,请显示'm.FullName'的限制。 “fi”是什么类型?更多:'FindRows'返回所有匹配的行。您的foreach循环结果不会执行任何搜索。与此相反,LINQ使用延迟执行,并将在您的'foreach'循环内执行搜索。为了正确比较运行时间,需要比较LINQ'foreach'和'FindRows' + foreach'循环的持续时间。 –

+0

这看起来不正确。 ManifestEntry.FullName在做什么?它是从文件加载吗? –

+0

我想你首先运行LINQ查询,然后是数据GRIDEVIEW查询,在这一步中,所有文件加载,所以数据网格运行速度快,但如果你反转执行路径,你会得到另一个结果。 –

回答

1

你的数据视图是由全名排序,因此FindRows可以直接跳转到正确的记录(s),而你的linq查询必须遍历列表直到它到达正确的记录。 如果您有500,000个条目,这一定会很明显。

假设全名是唯一的,那么当你切换到使用字典,我就怀疑你是通过它使用类似的LINQ查询还是迭代,像

var matchingME = (from m in manifest where m.Key == fi.FullName select m).Single(); 

而你应该使用

var matchingME = manifest[fi.FullName] ; 
+0

你传说@sgmoore!这(几乎)正是我所减去的'.single()'。不幸的是,我已经撕掉了对象的代码,并用数据表替换。我意识到字典解决方案对我来说不起作用,因为文件可能不止一次地出现在清单中 - 即FullName可能不是唯一的 - 在删除和修改文件副本的情况下。所以即使你的解决方案,我仍然被卡住。这是否仍然让linq变得干燥? – RichieRich

+0

@RichieRich你问'这是否仍然留下linq高和干?那么,我不是一个关于如何实现对象的专家,所以并不真正有资格回答这个问题,但我不会在这种情况下使用它。如果我从一个List 开始,我可能会使用ToDictionary(如果该键是唯一的),否则我会使用ToLookup。 – sgmoore