2011-09-06 117 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