[英]LINQ GroupBy extremely slow
以下代碼需要 5 分鍾才能在 100,000 行上運行。 這對我來說似乎很瘋狂。 我究竟做錯了什么?
var query =
from foo in fooStuff.AsEnumerable()
group foo by foo.Field<Int64>("FooID") into g
select new
{
FooID = g.Key,
FooTier = g.Min(foo => foo.Field<int>("Tier"))
};
注意:在 Mono 上。
當您調用 AsEnumerable() 時,您正在實現所有實體,因此您的分組是在 memory 中完成的。 嘗試刪除該部分,以便在數據庫級別完成分組:
var query =
from foo in fooStuff
group foo by foo.FooID into g
select new
{
FooID = g.Key,
FooTier = g.Min(foo => foo.Tier)
};
這不是直接比較,也不是在 Mono 上,但我有一些代碼與 6MB xml 文件類似,我讀入數據集,它有 30,000 行,需要 0.5 秒,所以我不認為是導致問題的 groupby 本身。
為了進一步診斷,我建議
測試將信息讀入列表需要多長時間,即
var fooList = fooStuff.AsEnumerable().ToList();
測試如果將查詢更改為使用 fooList 而不是 fooStuff 需要多長時間
測試如果從 select 中刪除 FooTier = g.Min(foo => foo.Tier) 需要多長時間
將.Field<> 反射從groupby 中分離出來並對每個部分進行計時,即首先將數據表中的信息讀入一個列表中,例如
var list2 = (from foo in fooStuff.AsEnumerable() select new { FooID = foo.Field<Int64>("FooID") Tier = foo.Field<int>("Tier") }).ToList();
然后你可以查詢這個列表
var query = from foo in list2 group foo by foo.FooID into g select new { FooID = g.Key, FooTier = g.Min(foo => foo.Tier) }; var results = query.ToList();
如果這個查詢很慢,則表明 mono 的 GroupBy 實現有問題。 您也許可以通過使用類似這樣的東西來驗證這一點
public static Dictionary<TKey, List<TSrc>> TestGroupBy<TSrc, TKey>
(this IEnumerable<TSrc> src, Func<TSrc,TKey> groupFunc)
{
var dict= new Dictionary<TKey, List<TSrc>>();
foreach (TSrc s in src)
{
TKey key = groupFunc(s);
List<TSrc> list ;
if (!dict.TryGetValue(key, out list))
{
list = new List<TSrc>();
dict.Add(key, list);
}
list.Add(s);
}
return dict;
}
並使用它
var results = list2.TestGroupBy(r=>r.FooID)
.Select(r=> new { FooID = r.Key, FooTier = r.Value.Min(r1=>r1.Tier)} );
請注意,這並不意味着替代 groupby 並且不處理 null 鍵,但應該足以確定它們是否是 groupby 的問題(假設 mono 的 Dictionary 和 List 實現是好的)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.