[英]How to optimize a code using DataTable and Linq?
我有 2 個數據表。 大約有17000條(table1)和100000條(table2)記錄。
需要檢查字段“FooName”是否包含“ ItemName ”。 還需要取“FooId” ,然后將“ItemId”和“FooId”添加到 ConcurrentDictionary。
我有這個代碼。
DataTable table1;
DataTable table2;
var table1Select = table1.Select();
ConcurrentDictionary<double, double> compareDictionary = new ConcurrentDictionary<double, double>();
foreach (var item in table1)
{
var fooItem = from foo in table2.AsEnumerable()
where foo.Field<string>("FooName").Contains(item.Field<string>("ItemName"))
select foo.Field<double>("FooId");
if(fooItem != null && fooItem.FirstOrDefault() != 0)
{
compareDictionary.TryAdd(item.Field<double>("ItemId"), fooItem.FirstOrDefault());
}
}
它工作緩慢(執行任務大約需要 10 分鍾)。
我想讓它更快。 我該如何優化它?
我看你可以攻擊三點:
doubles
是值類型。 upd正如評論中指出的那樣,無論哪種方式都不會避免取消裝箱,但可能會節省一些方法調用開銷(這也是有爭議的)。 這點大概可以忽略FirstOrDefault()
- 不要讓它在找到匹配項時枚舉整個事情ConcurrentDictionary<double, double> compareDictionary = new ConcurrentDictionary<double, double>();
foreach (var item in table1)
{
var sample = (string)item["ItemName"]; // cache the value before looping through inner collection
var fooItem = table2.AsEnumerable()
.FirstOrDefault(foo => ((string)foo["FooName"]).Contains(sample)); // you seem to always take First item, so you could instruct LINQ to stop after a match is found
if (fooItem != null && (double)fooItem["FooId"] != 0)
{
compareDictionary.TryAdd((double)item["ItemId"], (double)fooItem["FooId"]);
}
}
看來,將.FirstOrDefault()
條件應用於 LINQ 查詢語法無論如何都會將其簡化為方法鏈語法,所以我會一直選擇方法鏈,讓您自己來弄清楚美學
如果您願意為了速度而犧牲內存,那么從DataTable
轉換為您需要的字段可以比重復從table2
提取列數據的速度提高大約 6 倍。 (這是對使用FirstOrDefault
的加速的FirstOrDefault
。)
var compareDictionary = new ConcurrentDictionary<double, double>();
var t2e = table2.AsEnumerable().Select(r => (FooName: r.Field<string>("FooName"), FooId: r.Field<double>("FooId"))).ToList();
foreach (var item in table1.AsEnumerable().Select(r => (ItemName: r.Field<string>("ItemName"), ItemId: r.Field<double>("ItemId")))) {
var firstFooId = t2e.FirstOrDefault(foo => foo.FooName.Contains(item.ItemName)).FooId;
if (firstFooId != 0.0) {
compareDictionary.TryAdd(item.ItemId, firstFooId);
}
}
我使用 C# ValueTuple
來避免匿名類的引用對象開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.