繁体   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