簡體   English   中英

如何優化SQL Server Management Studio中的Entity Framework生成的SQL查詢?

[英]How to optimize SQL query generated by Entity Framework in SQL Server Management Studio?

我在linq中創建了一個查詢,它返回了我店里最活躍的銷售人員的表格:

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.

執行計划屏幕截圖

我想優化生成的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.

因此,在使用index優化SQL查詢后需要更長的時間。

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

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

Bzzt。 錯誤。

您的查詢已經“優化” - 因為您無法對查詢本身執行任何操作來提高其運行時性能。

SQL Server中的存儲過程與立即執行的查詢相比, 沒有任何神奇優化或其他真正的優勢。 存儲過程確實受益於緩存的執行計划,但是在第一次執行后立即查詢也是如此,並且執行計划生成並不是那么昂貴的操作。

無論如何,使用存儲過程進行只讀SELECT操作是不可取的,最好使用UDF( CREATE FUNCTION ),這樣你就可以利用可以優化的函數組合和比嵌套存儲過程調用更好的運行時。

如果SQL Server的“顯示執行計划”功能告訴您創建索引,這超出了EF的職責范圍,那么它也不在存儲過程的責任范圍內。 只需在數據庫中定義索引並將其包含在安裝腳本中即可。 如果不是存儲過程,EF生成的查詢將運行得更快。

任何人都可以幫助我使用索引在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();

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM