【问题标题】:How to optimize SQL query generated by Entity Framework in SQL Server Management Studio?如何在 SQL Server Management Studio 中优化实体框架生成的 SQL 查询?
【发布时间】:2016-01-16 11:28:50
【问题描述】:

我在 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();

继承的 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

我想优化生成的 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 中使用索引优化这个查询?

【问题讨论】:

  • 创建索引后不会花费 太多 - CPU 时间实际上是 down .... 你看过 查询的实际执行计划创建索引之前,之后呢?查看发生了什么变化 - 它可能会向您展示有关如何进一步改进您的查询的其他提示
  • 您的查询有问题。先从为什么加入两个表(将tblUsers 中的记录相乘)然后不使用投影中的第二个表记录。

标签: c# sql sql-server entity-framework linq


【解决方案1】:

谁能帮我在 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();

尝试查看新的执行计划/时间。

【讨论】:

    【解决方案2】:

    我想优化生成的 SQL 查询并将优化后的查询插入到存储过程中。

    Bzzt。错了。

    您的查询已经“优化”——因为您无法对查询本身做任何事情来提高其运行时性能。

    SQL Server 中的存储过程没有与立即执行的查询相比,没有任何魔法优化或其他真正的优势。存储过程确实受益于缓存的执行计划,但在第一次执行后立即查询也是如此,并且执行计划的生成并不是一项昂贵的操作。

    无论如何,使用存储过程进行只读SELECT 操作是不可取的,最好使用UDF (CREATE FUNCTION),这样您就可以利用可以优化的函数组合,并且运行时比嵌套存储要好得多过程调用。

    如果 SQL Server 的显示执行计划功能告诉您创建索引,这不在 EF 的职责范围内,它也超出了存储过程的职责范围。只需在数据库中定义索引并将其包含在设置脚本中即可。如果不是存储过程,您的 EF 生成的查询将运行得更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      • 1970-01-01
      • 2014-02-18
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多