【发布时间】:2020-06-11 05:35:34
【问题描述】:
我们一直在 Linq 模式下查询 DataTable 中的数据,并且从未遇到任何性能问题。直到以下情况,使用 Linq 需要 600s+,但使用 DataTable.Select() 只需要 3s。结果是一致的。直觉告诉我Linq不应该这么慢,而且我的操作有问题,但我不知道如何改进它,谁能给我一些建议?
GetDtTest_Base() 和 GetDtTest_Info() 是在 ADO.NET 中通过 SqlDataAdapter 从 Sql Server 返回的 DataTable 和 DataSet。
DataTable dtBase = GetDtTest_Base(); //4W rows
DataSet dsInfo = GetDtTest_Info(); //two Datatable 4W rows, 2K rows
//Normally, we use Linq all the time. In this scenario, it takes about 600 seconds to query through Linq
foreach (DataRow item in dtBase.Rows)
{
string pnum = item["pnum"].ToString();
string number = item["number"].ToString();
var query_Info1 = dsInfo.Tables[0].AsEnumerable()
.Where(w => w.Field<string>("pnum") == pnum && w.Field<string>("calleee164") == number)
.Select(s => s);
item["conn"] = query_Info1.Count() > 0 ? (query_Info1.First())["conn"] : 0;
item["total"] = query_Info1.Count() > 0 ? (query_Info1.First())["total"] : 0;
var query_Info2 = dsInfo.Tables[1].AsEnumerable()
.Where(w => w.Field<string>("pnum") == pnum && w.Field<string>("calleee164") == number)
.Select(s => s);
item["asCnt"] = query_Info2.Count() > 0 ? 1 : 0;
item["asTrunks"] = query_Info2.Count() > 0 ? (query_Info2.First())["trunks"] : null;
}
//After changing this query, it only took 3 seconds to query
foreach (DataRow item in dtBase.Rows)
{
string pnum = item["pnum"].ToString();
string number = item["number"].ToString();
DataRow[] query_Info1 = dsInfo.Tables[0].Select($"pnum='{pnum}' and calleee164='{number}'");
if (query_Info1 != null && query_Info1.Length >= 1)
{
item["conn"] = query_Info1[0]["conn"].ToString();
item["total"] = query_Info1[0]["total"].ToString();
}
else
{
item["conn"] = 0;
item["total"] = 0;
}
DataRow[] query_Info2 = dsInfo.Tables[1].Select($"pnum='{pnum}' and calleee164='{number}'");
if (query_Info2 != null && query_Info2.Length >= 1)
{
item["asCnt"] = 1;
item["asTrunks"] = query_Info2[0]["trunks"].ToString();
}
else
{
item["asCnt"] = 0;
item["asTrunks"] = null;
}
}
【问题讨论】:
-
尝试将
dsInfo.Tables[0].AsEnumerable()移到foreach循环之外,因为这可能会产生开销。 -
var query_Info10 = dsInfo.Tables[0].AsEnumerable(); var query_Info20 = dsInfo.Tables[1].AsEnumerable(); foreach (DataRow item in dtBase.Rows) { ... ... var query_Info1 = query_Info10 .Where... ... } 问题依旧存在
-
每次迭代查询两个数据表 4 次,Count 和 First,两次,而同样的事情可以在一次
FirstOrDefault()调用中完成。
标签: c# performance linq datatable