2013-04-15 61 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是統計上的好文章,並給出了一個很好擊穿上它們是什麼,他們做什麼,以及如何看待他們。