2012-11-01 40 views
2

Wee從DB加載大對象圖。 查詢有許多包含和Where()使用Contains()過濾最終結果。 包含大約一千個條目的集合被調用。什麼是使用Contains()優化實體框架查詢的方法?

分析器顯示可怕的人類無法讀取的SQL。 由於Contains(),查詢無法預編譯。

有沒有什麼方法可以優化這些查詢?

更新

public List<Vulner> GetVulnersBySecurityObjectIds(int[] softwareIds, int[] productIds) 
     { 
      var sw = new Stopwatch(); 

      var query = from vulner in _businessModel.DataModel.VulnerSet 
         join vt in _businessModel.DataModel.ObjectVulnerTieSet.Where(ovt => softwareIds.Contains(ovt.SecurityObjectId)) 
         on vulner.Id equals vt.VulnerId 
         select vulner; 

      var result = ((ObjectQuery<Vulner>)query.OrderBy(v => v.Id).Distinct()) 
       .Include("Descriptions") 
       .Include("Data") 
       .Include("VulnerStatuses") 
       .Include("GlobalIdentifiers") 
       .Include("ObjectVulnerTies") 
       .Include("Object.ProductObjectTies.Product") 
       .Include("VulnerComment"); 

      //Если переданы конкретные продукты, добавляем фильтрацию 
      if (productIds.HasValues()) 
       result = (ObjectQuery<Vulner>)result.Where(v => v.Object.ProductObjectTies.Any(p => productIds.Contains(p.ProductId))); 

      sw.Start(); 
      var str = result.ToTraceString(); 
      sw.Stop(); 
      Debug.WriteLine("Сборка запроса заняла {0} секунд.", sw.Elapsed.TotalSeconds); 
      sw.Restart(); 
      var list = result.ToList(); 
      sw.Stop(); 
      Debug.WriteLine("Получение уязвимостей заняло {0} секунд.", sw.Elapsed.TotalSeconds); 

      return list; 
     } 
+0

也許,但不是沒有看到你正在嘗試做什麼的例子... – PinnyM

+0

明天只。代碼留在辦公室=) –

+0

我認爲包含使用像%%''應該可以通過全文檢索索引在sql –

回答

2

幾乎可以肯定,在片將查詢執行得更好,儘管更多的分貝往返。總是建議限制包含的數量,因爲它們不僅會炸開查詢的大小和複雜性(正如您注意到的那樣),還會炸燬長度和寬度的結果集。而且,他們經常被翻譯成外連接。

除此之外,使用Contains你的方式是OK。

對不起,如果不知道您的數據模型和涉及的表的大小,則很難更具體。

+2

關於EF性能的好文章http:// msdn.microsoft.com/en-us/data/hh949853.aspx –

+1

偉大的藝術!有關我們問題的重要引言:「一旦將三個或更多實體包含到查詢中,請考慮切換到延遲加載。」而「對於包含多個Include語句的查詢來說,通過我們的內部計劃編譯器需要相當長的時間」。而且「像這樣的查詢將在單個有效載荷中引入來自數據庫的大型連接圖,這將消除任何帶寬問題」。 –

相關問題