2016-01-16 28 views
3

我創建LINQ查詢返回最活躍的推銷員的表在我店:如何優化由SQL Server Management Studio中的實體框架生成的SQL查詢?

ProjectDB3Context db = new ProjectDB3Context(); 

db.Database.Log = message => Trace.WriteLine(message); 
var result = db.tblUsers.Join(db.tblSales, 
           u => u.ID, 
           sl => sl.tblUserId, 
           (u, sl) => new { u, sl }) 
       .Select(o => new 
          { 
           UserId = o.u.ID, 
           Login = o.u.UserLogin, 
           FullName = o.u.Name + " " + o.u.Surname, 
           ItemsToSell = db.tblSales.Where(x => x.tblUserId == o.u.ID).Count() 
          }) 
       .Distinct() 
       .OrderByDescending(x => x.ItemsToSell) 
       .ToList(); 

的henerated SQL查詢看起來像:

SELECT 
    [Distinct1].[C1] AS [C1], 
    [Distinct1].[ID] AS [ID], 
    [Distinct1].[UserLogin] AS [UserLogin], 
    [Distinct1].[C2] AS [C2], 
    [Distinct1].[C3] AS [C3] 
    FROM (SELECT DISTINCT 
     [Project1].[ID] AS [ID], 
     [Project1].[UserLogin] AS [UserLogin], 
     1 AS [C1], 
     [Project1].[Name] + N' ' + [Project1].[Surname] AS [C2], 
     [Project1].[C1] AS [C3] 
     FROM (SELECT 
      [Extent1].[ID] AS [ID], 
      [Extent1].[UserLogin] AS [UserLogin], 
      [Extent1].[Name] AS [Name], 
      [Extent1].[Surname] AS [Surname], 
      (SELECT 
       COUNT(1) AS [A1] 
       FROM [dbo].[tblSale] AS [Extent3] 
       WHERE [Extent3].[tblUserId] = [Extent1].[ID]) AS [C1] 
      FROM [dbo].[tblUser] AS [Extent1] 
      INNER JOIN [dbo].[tblSale] AS [Extent2] ON [Extent1].[ID] = [Extent2].[tblUserId] 
     ) AS [Project1] 
    ) AS [Distinct1] 
    ORDER BY [Distinct1].[C3] DESC 

統計:

SQL Server Execution Times: 
CPU time = 359 ms, elapsed time = 529 ms. 

Execution plan screen shot

我想優化gen erated SQL查詢並將優化後的查詢插入到存儲過程中。 SQL Server Management Studio爲我提供了一個技巧,可以在tblSale上創建非聚集索引(tblUserId)(您可以在包含的圖像中看到此提示)。

當我創建使用命令它:

CREATE NONCLUSTERED INDEX IX_ProductVendor_tblUserId 
ON tblSale (tblUserId); 

,然後運行在SQL Server Management Studio中的SQL查詢,我得到:

SQL Server Execution Times: 
CPU time = 328 ms, elapsed time = 631 ms. 

所以需要更長的時間我使用的索引後優化我的SQL查詢。

任何人都可以幫助我在SQL Server中使用索引優化此查詢嗎?

+2

創建索引後,它不需要太長的時間* CPU時間實際上是**下降** ....您是否在*創建之前查看了**實際執行計劃**索引和之後?看看有什麼變化 - 它可能會告訴你關於如何進一步改善您的查詢的其他技巧 –

+0

您的查詢有問題。首先介紹爲什麼要加入兩個表(它將'tblUsers'中的記錄相乘),然後不在投影中使用第二個表記錄。 –

回答

3

任何人都可以幫助我在SQL Server中使用索引優化此查詢嗎?

首先,在嘗試優化數據庫中的SQL查詢之前,請確保您的LINQ查詢是最優的。你的情況並非如此。有沒有必要的加入,這反過來需要明確等。並且tblSales被訪問兩次(請參閱生成的SQL)。

您試圖實現的目標是按銷售數量降序銷售銷售的用戶。以下簡單查詢應產生所需結果

var result = db.tblUsers 
    .Select(u => new 
    { 
     UserId = u.ID, 
     Login = u.UserLogin, 
     FullName = u.Name + " " + u.Surname, 
     ItemsToSell = db.tblSales.Count(s => s.tblUserId == u.ID) 
    }) 
    .Where(x => x.ItemsToSel > 0) 
    .OrderByDescending(x => x.ItemsToSell) 
    .ToList(); 

嘗試並查看新的執行計劃/時間。

3

我想優化生成的SQL查詢並將優化的查詢插入存儲過程。

Bzzt。錯誤。

您的查詢已經「優化」 - 因爲您無法對查詢本身做任何事情來提高其運行時性能。

SQL Server中的存儲過程不具有與立即執行的查詢相比,具有任何形式的魔術優化或其他實際優勢。存儲過程確實從緩存的執行計劃中受益,但在第一次執行之後也立即進行查詢,並且執行計劃的生成對於操作來說並不昂貴。

總之,使用存儲過程的只讀SELECT操作是inadvisble,最好是使用UDF(CREATE FUNCTION),這樣你可以採取哪些可以優化和運行時間遠遠超過嵌套的存儲過程調用的更多功能成分的優勢。

如果SQL Server的顯示執行計劃功能告訴您創建一個不在EF責任範圍內的索引,它也不在存儲過程的責任範圍之內。只需在數據庫中定義索引並將其包含在設置腳本中即可。您的EF生成的查詢將運行得更快,而不是存儲過程。

相關問題