选择SQL View Slow with table alias

时间:2015-12-08 18:35:14

标签: sql entity-framework tsql table-alias

我很困惑为什么在使用表别名(25秒)时选择我的SQL视图是如此之慢,但是当别名被删除(2秒)时运行速度要快得多

- 此查询需要25秒。

SELECT [Extent1].[Id]                        AS [Id],
       [Extent1].[ProjectId]                 AS [ProjectId],
       [Extent1].[ProjectWorkOrderId]        AS [ProjectWorkOrderId],
       [Extent1].[Project]                   AS [Project],
       [Extent1].[SubcontractorId]           AS [SubcontractorId],
       [Extent1].[Subcontractor]             AS [Subcontractor],
       [Extent1].[ValuationNumber]           AS [ValuationNumber],
       [Extent1].[WorksOrderName]            AS [WorksOrderName],
       [Extent1].[NewGross],
       [Extent1].[CumulativeGross],
       [Extent1].[CreateByName]              AS [CreateByName],
       [Extent1].[CreateDate]                AS [CreateDate],
       [Extent1].[FinalDateForPayment]       AS [FinalDateForPayment],
       [Extent1].[CreateByEmail]             AS [CreateByEmail],
       [Extent1].[Deleted]                   AS [Deleted],
       [Extent1].[ValuationStatusCategoryId] AS [ValuationStatusCategoryId]
FROM   [dbo].[ValuationsTotal] AS [Extent1] 

- 此查询需要2秒。

SELECT [Id],
       [ProjectId],
       [Project],
       [SubcontractorId],
       [Subcontractor],
       [NewGross],
       [ProjectWorkOrderId],
       [ValuationNumber],
       [WorksOrderName],
       [CreateByName],
       [CreateDate],
       [CreateByEmail],
       [Deleted],
       [ValuationStatusCategoryId],
       [FinalDateForPayment],
       [CumulativeGross]
FROM   [dbo].[ValuationsTotal] 

这是我的SQL查看代码 -

WITH ValuationTotalsTemp(Id, ProjectId, Project, SubcontractorId, Subcontractor, WorksOrderName, NewGross, ProjectWorkOrderId, ValuationNumber, CreateByName, CreateDate, CreateByEmail, Deleted, ValuationStatusCategoryId, FinalDateForPayment)
     AS (SELECT vi.ValuationId                             AS Id,
                v.ProjectId,
                p.NAME,
                b.Id                                       AS Expr1,
                b.NAME                                     AS Expr2,
                wo.OrderNumber,
                SUM(vi.ValuationQuantity * pbc.BudgetRate) AS 'NewGross',
                sa.ProjectWorkOrderId,
                v.ValuationNumber,
                up.FirstName + ' ' + up.LastName           AS Expr3,
                v.CreateDate,
                up.Email,
                v.Deleted,
                v.ValuationStatusCategoryId,
                sa.FinalDateForPayment
         FROM   dbo.ValuationItems AS vi
                INNER JOIN dbo.ProjectBudgetCosts AS pbc
                        ON vi.ProjectBudgetCostId = pbc.Id
                INNER JOIN dbo.Valuations AS v
                        ON vi.ValuationId = v.Id
                INNER JOIN dbo.ProjectSubcontractorApplications AS sa
                        ON sa.Id = v.ProjectSubcontractorApplicationId
                INNER JOIN dbo.Projects AS p
                        ON p.Id = v.ProjectId
                INNER JOIN dbo.ProjectWorkOrders AS wo
                        ON wo.Id = sa.ProjectWorkOrderId
                INNER JOIN dbo.ProjectSubcontractors AS sub
                        ON sub.Id = wo.ProjectSubcontractorId
                INNER JOIN dbo.Businesses AS b
                        ON b.Id = sub.BusinessId
                INNER JOIN dbo.UserProfile AS up
                        ON up.Id = v.CreateBy
         WHERE ( vi.Deleted = 0 )
               AND ( v.Deleted = 0 )
         GROUP  BY vi.ValuationId,
                   v.ProjectId,
                   p.NAME,
                   b.Id,
                   b.NAME,
                   wo.OrderNumber,
                   sa.ProjectWorkOrderId,
                   v.ValuationNumber,
                   up.FirstName + ' ' + up.LastName,
                   v.CreateDate,
                   up.Email,
                   v.Deleted,
                   v.ValuationStatusCategoryId,
                   sa.FinalDateForPayment)
SELECT Id,
       ProjectId,
       Project,
       SubcontractorId,
       Subcontractor,
       NewGross,
       ProjectWorkOrderId,
       ValuationNumber,
       WorksOrderName,
       CreateByName,
       CreateDate,
       CreateByEmail,
       Deleted,
       ValuationStatusCategoryId,
       FinalDateForPayment,
       (SELECT SUM(NewGross) AS Expr1
        FROM   ValuationTotalsTemp AS tt
        WHERE ( ProjectWorkOrderId = t.ProjectWorkOrderId )
              AND ( t.ValuationNumber >= ValuationNumber )
        GROUP  BY ProjectWorkOrderId) AS CumulativeGross
FROM   ValuationTotalsTemp AS t 

为什么会这样?

SQL查询使用表别名运行,因为它是从Entity Framework生成的,所以我无法更改它。我将需要修改我的SQL视图,以便能够处理表别名而不影响性能。

3 个答案:

答案 0 :(得分:2)

执行计划非常不同。

缓慢的部分有一部分跳出来是有问题的。它估计单行将输入到嵌套循环连接,并导致ValuationItems的单次扫描。在实践中,它最终会执行超过1,000次此类扫描。

估计

enter image description here

实际

enter link description here

SQL Server 2014引入了新的基数估算器。您的快速计划正在使用它。这在XML中显示为CardinalityEstimationModelVersion="120"您的慢速计划不是(CardinalityEstimationModelVersion="70")。

所以看起来在这种情况下,新估算师使用的假设会给你一个更好的计划。

差异的原因可能是快速运行跨数据库(参考[ProbeProduction]。[dbo]。[ValuationsTotal])并且可能是您执行它的数据库具有2014年的比较级别,因此自动获得新的CardinalityEstimator。

慢速在ProbeProduction本身的上下文中执行,我假设该数据库的兼容级别必须是< 2014年 - 因此您违反了传统的基数估算器。

您可以使用OPTION (QUERYTRACEON 2312)来获取慢查询以使用新的基数估算器(如果不仔细测试现有查询,则不应更改数据库兼容性模式以全局更改行为,因为它可能导致回归以及改进)。

或者,您可以尝试在遗留CE的限制范围内调整查询。也许添加联接提示以鼓励它使用更类似于更快计划的东西。

答案 1 :(得分:1)

两个查询不同(列顺序!)。假设第一个查询使用索引是合理的,因此更快。我怀疑这与评论有什么关系。

答案 2 :(得分:0)

咧嘴笑着取出去哪儿试试? 我可能会在最后做一堆循环连接和过滤 这可能会让它过滤前面的

FROM       dbo.ValuationItems AS vi
INNER JOIN dbo.Valuations     AS v
             ON vi.ValuationId = v.Id
            AND vi.Deleted = 0 
            AND  v.Deleted = 0 
-- other joins 
-- NO where

如果你有很多循环连接,那么尝试内部散列连接(在所有)