2013-04-15 34 views
2

我想查看简单的选择顶部(n)的查询计划。每当我改变n(我得到的记录数)时,查询计划会发生变化,Select Top 10特别会导致性能问题,如果查询计数少于10或大于10,查询将顺利运行。不同的SQL查询计划与选择顶部(n)

查询由实体框架(4.2)生成,如果它有所作为。

查询是:

exec sp_executesql N'SELECT TOP (10) 
[Project1].[Id] AS [Id], 
[Project1].[DateReceived] AS [DateReceived], 
[Project1].[Status] AS [Status], 
[Project1].[Subject] AS [Subject], 
[Project1].[Description] AS [Description], 
[Project1].[Path] AS [Path], 
[Project1].[C1] AS [C1], 
[Project1].[C2] AS [C2], 
[Project1].[C3] AS [C3], 
. 
. 
. 
. 
. 
. 
. 

WHERE [Project1].[row_number] > 0 
ORDER BY [Project1].[DateReceived] DESC',N'@p__linq__0 int,@p__linq__1 int,@p__linq__2 datetime2(7),@p__linq__3 datetime2(7),@p__linq__4 nvarchar(4000),@p__linq__5 nvarchar(4000),@p__linq__6 nvarchar(4000),@p__linq__7 nvarchar(4000)',@p__linq__0=-1,@p__linq__1=-1,@p__linq__2='2013-03-15 00:00:00',@p__linq__3='2013-04-15 23:59:55',@p__linq__4=N'ALL',@p__linq__5=N'ALL',@p__linq__6=N'',@p__linq__7=N'%%' 

为什么TOP 10特别是导致性能问题?

我不能分享图片的是,这里是链接:

http://imageshack.us/photo/my-images/407/top10a.png/

http://imageshack.us/photo/my-images/580/top20x.png/

+0

什么是你的**问题**? – Luv

+1

你可以发布执行计划吗?这将是非常有帮助的。 我的第一个想法: SQL Server使用它的统计信息更改它的执行计划。你可以假设更新统计。 –

+0

执行计划添加到我的问题上面。 –

回答

0

正如@JanDrozen说,它最有可能是统计的问题。当数据大小超过某个阈值时,生成的执行计划不再是最佳计划,但统计数据不允许它获得正确的估计行数。优化器并不总是生成最佳的执行计划。这是一个令人印象深刻的编程成就,它通常会从我们的cha making中赚取黄金,但它实际上只能尽其所能地利用其掌握的数据。它使用肉食性统计数据,并将使用估算的结果集大小来确定它认为最好的计划。

如果不先尝试更新统计信息是否属于统计问题,则可以启用实际执行计划并查看属性。

检查:

  • 当数据进入管道,该行的估计数是接近实际的行数。
  • 执行计划的属性表示优化程序已达到最佳计划。在物业中,它会告诉你为什么选择这个计划。有时,如果统计数据过时,优化程序从不会找到最佳计划,只需使用它可以找到的最佳计划即可。

该查询是更新示例adventureworks数据库中的统计信息的示例。

USE AdventureWorks2012; 
GO 
UPDATE STATISTICS Production.Product(Products) 
    WITH FULLSCAN, NORECOMPUTE; 
GO 

有一个存储过程sp_updatestats [ [ @resample = ] 'resample'] ,但我从未有过它的伟大成果,我永远无法迫使它采用了全扫描,这是我的经验,以获得良好的统计数据的最佳方式进行更新。

如果您需要为大量表执行此操作,以下是我之前使用过的使用动态SQL重新生成统计信息的脚本。

DECLARE @sql nvarchar(MAX); 
SELECT @sql = (SELECT 'UPDATE STATISTICS ' + 
        quotename(s.name) + '.' + quotename(o.name) + 
        ' WITH FULLSCAN; ' AS [text()] 
      FROM sys.objects o 
      JOIN sys.schemas s ON o.schema_id = s.schema_id 
      WHERE o.type = 'U' 
      FOR XML PATH(''), TYPE).value('.', 'nvarchar(MAX)'); 
PRINT @sql 
EXEC (@sql) 

Here是统计上的好文章,并给出了一个很好击穿上它们是什么,他们做什么,以及如何看待他们。