2012-11-06 31 views
3

我使用IEqualityComparer来匹配使用LINQ to Entities的数据库中的“near duplicates”。使用IEqualityComparer提高LINQ查询的性能

记录集大约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(); 
     } 
    } 
+0

我会使分隔符数组静态只读,但我怀疑这是一个性能改进很大。 –

+0

写入存储过程? – Liam

+0

是的,你真的应该尽可能在DB端做更多的事情,而不是全部都在内存中。这最终会变得非常快。 – Servy

回答

2

一种方法是在DB上创建一个计算列,该列是公司名称,不需要的字符被删除。

然后使用此列进行过滤。

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

+0

这是一个很好的建议。你会建议为此做一个函数吗? – Nick

+0

是的,这里是可以改编的东西... http://davidbridge.wordpress.com/2011/04/11/sql-server-alltrim/ –

+0

这是我的答案。谢谢! – Nick

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(); 
    } 
} 

威力更快;试一试! (另外请注意我跳过空检查,你可能想把它们放回原处。)

+1

编译正则表达式(使用'RegexOptions.Compiled')可以(非常)稍微改进 –