我很困惑为什么在使用表别名(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视图,以便能够处理表别名而不影响性能。
答案 0 :(得分:2)
执行计划非常不同。
缓慢的部分有一部分跳出来是有问题的。它估计单行将输入到嵌套循环连接,并导致ValuationItems的单次扫描。在实践中,它最终会执行超过1,000次此类扫描。
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
如果你有很多循环连接,那么尝试内部散列连接(在所有)