【问题标题】:Improving performance of LINQ query with IEqualityComparer使用 IEqualityComparer 提高 LINQ 查询的性能
【发布时间】:2012-11-06 23:04:52
【问题描述】:

我正在使用IEqualityComparer 匹配使用 LINQ to Entities 的数据库中的“近似重复项”。

记录集约为 40,000,此查询大约需要 15 秒才能完成,我想知道是否可以对下面的代码进行任何结构更改。

我的公共方法

public List<LeadGridViewModel> AllHighlightingDuplicates(int company)
        {

            var results = AllLeads(company)
                  .GroupBy(c => c, new CompanyNameIgnoringSpaces())
                  .Select(g => new LeadGridViewModel
                  {
                      LeadId = g.First().LeadId,
                      Qty = g.Count(),
                      CompanyName = g.Key.CompanyName
                  }).OrderByDescending(x => x.Qty).ToList();

            return results;

        }

获取潜在客户的私人方法

private char[] delimiters = new[] { ' ', '-', '*', '&', '!' };
private IEnumerable<LeadGridViewModel> AllLeads(int company)
        {
            var items = (from t1 in db.Leads
                          where
                              t1.Company_ID == company
                          select new LeadGridViewModel
                          {
                              LeadId = t1.Lead_ID,
                              CompanyName = t1.Company_Name,
                          }).ToList();


            foreach (var x in items)
                x.CompanyNameStripped = string.Join("", (x.CompanyName ?? String.Empty).Split(delimiters));

            return items;
        }

我的 IEqualityComparer

 public class CompanyNameIgnoringSpaces : IEqualityComparer<LeadGridViewModel>
    {
        public bool Equals(LeadGridViewModel x, LeadGridViewModel y)
        {
            var delimiters = new[] {' ', '-', '*', '&', '!'};
            return delimiters.Aggregate(x.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0')) 
                == delimiters.Aggregate(y.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0'));
        }

        public int GetHashCode(LeadGridViewModel obj)
        {
            var delimiters = new[] {' ', '-', '*', '&', '!'};
            return delimiters.Aggregate(obj.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0')).GetHashCode();
        }
    }

【问题讨论】:

  • 我将 delimiters 数组设为静态只读,但我怀疑这是否会大大提高性能。
  • 是的,您确实应该在数据库端尽可能多地执行此操作,而不是全部在内存中。这很可能最终会快得多

标签: c# performance linq


【解决方案1】:

一种方法是在数据库上创建一个计算列,即删除不需要的字符的公司名称。

然后使用此列进行过滤。

这可能会稍微降低插入性能,但应该会大大缩短查询时间。

【讨论】:

【解决方案2】:

您可以使用Regex.Replace 一次性执行所有替换:

public class CompanyNameIgnoringSpaces : IEqualityComparer<LeadGridViewModel>
{
    static Regex replacer = new Regex("[ -*&!]");
    public bool Equals(LeadGridViewModel x, LeadGridViewModel y)
    {
        return replacer.Replace(x.CompanyName, "")
            == replacer.Replace(y.CompanyName, "");
    }

    public int GetHashCode(LeadGridViewModel obj)
    {
        return replacer.Replace(obj.CompanyName, "").GetHashCode();
    }
}

可能会更快;试试看! (另请注意,我已跳过空值检查,您可能希望以某种方式将它们放回原处。)

【讨论】:

  • 通过编译正则表达式(使用RegexOptions.Compiled)可以(非常)稍微改进
猜你喜欢
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 2013-08-05
相关资源
最近更新 更多