c# - 比较数据表的有效方法

标签 c# performance linq

我有下面的 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;
}

此代码有效,但比较数据表中的 10,000 条记录需要 1.24 分钟。有什么办法可以让它更快?
N是主键和 columnName是要比较的列。

谢谢。

最佳答案

首先我会问你是否在一个简单的 for/foreach 循环中尝试过这个并比较了性能?

目前您正在创建一个新的 Enumerable,然后复制到数据表。
如果您使用 for/foreach 循环,那么您可以在同一次迭代中进行比较和复制。

您还应该查看字符串比较。目前您正在修剪然后转换为小写。这将为每个字符串的每个操作分配新的内存,因为字符串是不可变的。因此,在您的 where 语句中,您基本上每次迭代执行此操作(最多)8 次。

我也想问你是否真的需要Trim() ?一个 DT 是否有可能在字符串的前面有一个空格而另一个没有?还是比较仍然成立?除非真的需要,否则不要修剪字符串。

那么你应该使用不区分大小写的字符串比较而不是转换 ToLower .这样会更快。根据 MS StringComparison.OrdinalIgnoreCase性能更好。

做这些,然后比较性能,看看你有多少差异

也可以看看:
https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings

更新:

这引起了我的兴趣,所以我回去做了一些测试。
我在两个数据表中生成了 10,000 行随机(ish)数据,其中每隔一行将匹配并执行您的比较,而不是使用字符串比较的简化 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);
      }
  }

您的代码 = 66,000 毫秒 -> 75,000 毫秒

For 循环代码 = 12ms -> 20ms

一个显着的区别!

然后我使用 for 循环方法进行了比较,但对字符串使用了两种不同的字符串比较类型。使用我的字符串比较,与你的比较。但是我必须为此测试 100 万行,以获得显着差异。

这差异在 200 毫秒和 800 毫秒之间

因此,在这种情况下,字符串比较似乎不是主要因素。

因此,您的 Linq 查询创建数据行似乎占用了大部分时间,而不是行本身的比较。

所以切换到使用 for 循环,一切都会好起来的!

关于c# - 比较数据表的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61650083/

相关文章:

java - Android:提高音乐播放器应用的效率

c# - EntityFramework 中的 MySql ORDER BY FIELD()

c# 源数组不够长。检查 srcIndex 和长度,以及 Array.Copy 的数组下限

c# - 调用 native 代码的多线程托管应用程序

c# - WebClient 使用 JSON 并发送其属性值

c# - 林克 : Select multiple values and assign to select with specific option/value

c# - Linq 将数组匹配到列表?

c# - 什么时候可以将 2 个 View 模型合并为 1 个而不是使用某种形式的 View 模型- View 模型通信?

android - Android 的 Firebase ML Kit 人脸检测速度慢

performance - Jackson 2 : Parsing a ton of classes through JPA associations, 是否可以限制深度?