use*_*718 6 c# linq performance
我有下面的 c# 方法来比较两个数据表并返回不匹配的记录。
public DataTable GetTableDiff(DataTable dt1, DataTable dt2, string columnName)
{
var StartTime = DateTime.Now;
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["N"] };
dt2.PrimaryKey = new DataColumn[] { dt2.Columns["N"] };
DataTable dtDifference = null;
//Get the difference of two datatables
var dr = from r in dt1.AsEnumerable()
where !dt2.AsEnumerable().Any(r2 => r["N"].ToString().Trim().ToLower() == r2["N"].ToString().Trim().ToLower()
&& r[columnName].ToString().Trim().ToLower() == r2[columnName].ToString().Trim().ToLower())
select r;
if (dr.Any())
{
dtDifference = dr.CopyToDataTable();
}
return dtDifference;
}
Run Code Online (Sandbox Code Playgroud)
此代码有效,但比较数据表中的 10,000 条记录需要 1.24 分钟。有什么办法可以让它更快?
N
是主键,columnName
是要比较的列。
谢谢。
首先我想问您是否在简单的 for/foreach 循环中尝试过这个并比较了性能?
目前,您正在创建一个新的 Enumerable,然后复制到数据表。如果您使用 for/foreach 循环,那么您可以在同一迭代中进行比较和复制。
您还应该查看字符串比较。目前您正在修剪然后转换为小写。由于字符串是不可变的,这将为每个字符串的每个操作分配新的内存。因此,在您的 where 语句中,每次迭代基本上会执行此操作(最多)8 次。
我还想问你真的需要吗Trim()
?是否有可能一个 DT 在字符串前面有一个空格,而另一个 DT 则没有?或者比较仍然是正确的吗?除非确实需要,否则不要修剪琴弦。
那么您应该使用不区分大小写的字符串比较而不是转换ToLower
。这样会更快。根据 MS 的StringComparison.OrdinalIgnoreCase
说法,性能更好。
执行这些操作,然后比较性能,看看有多少差异
另请参阅: https ://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings
更新:
这引起了我的兴趣,所以我回去做了一些测试。我在两个数据表中生成了 10,000 行随机数据,其中每隔一行都会匹配并执行比较,而不是使用字符串比较进行简化的 for 循环比较,如下所示:
for (int i = 0; i < dt1.Rows.Count; i++)
{
if (dt1.Rows[i]["N"].ToString().Equals(dt2.Rows[i]["N"].ToString(), StringComparison.OrdinalIgnoreCase)
&& dt1.Rows[i][columnName].ToString().Equals(dt2.Rows[i][columnName].ToString(), StringComparison.OrdinalIgnoreCase))
{
dtDifference.Rows.Add(dt1.Rows[i].ItemArray);
}
}
Run Code Online (Sandbox Code Playgroud)
您的代码 = 66,000ms -> 75,000ms
For 循环代码 = 12ms -> 20ms
显着差异!
然后我使用 for 循环方法进行比较,但使用字符串的两种不同的字符串比较类型。使用我的字符串与你的字符串比较。但我必须为此测试 100 万行,才能获得显着差异。
相差 200 毫秒到 800 毫秒
所以在这种情况下,字符串比较似乎不是主要因素。
因此,创建数据行的 Linq 查询似乎花费了大部分时间,而不是行本身的比较。
所以改用 for 循环吧,一切都会好起来的!
归档时间: |
|
查看次数: |
84 次 |
最近记录: |