2012-11-06 30 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')可以(非常)稍微改進 –