![](/img/trans.png)
[英]Linq to SQL: Query runs fine in SQL Server Management Studio, but times out on the application
[英]Insert query times out in C# web app, runs fine from SQL Server Management Studio
我正在嘗試從我的C#Web應用程序運行插入查詢。 當我從SQL Server Management Studio運行查詢時,插入查詢大約需要五分鍾才能完成。 從應用程序運行時,它會在30分鍾后超時(是分鍾,而不是秒)。
我從VS調試器中獲取了實際的SQL語句並從Mgmt Studio運行它並且工作正常。
所有這些都是從我的開發環境運行,而不是生產環境。 查詢正在進行時,沒有其他SQL Server活動。 我正在使用SQL Server 2008 R2進行開發。 MS VS 2010 Express,Asp.Net 4.0。 SQL Server Mgmt Studio 10。
有一個類似的問題從未得到解答: 來自C#.NET的SQL server timeout 2000
這是來自以下的SET選項:dbcc useroptions
Option MgtStudio Application
----------------------- -------------- --------------
textsize 2147483647 -1
language us_english us_english
dateformat mdy mdy
datefirst 7 7
lock_timeout -1 -1
quoted_identifier SET SET
arithabort SET NOT SET
ansi_null_dflt_on SET SET
ansi_warnings SET SET
ansi_padding SET SET
ansi_nulls SET SET
concat_null_yields_null SET SET
isolation level read committed read committed
只有文本化和arithabort是不同的。
任何想法為什么在查詢執行時間有這么大的差異,以及我可以做些什么來縮小這種差異?
我不確定查詢會有多大用處,特別是因為包含模式會太多。 無論如何,這里是:
INSERT INTO GeocacherPoints
(CacherID,
RegionID,
Board,
Control,
Points)
SELECT z.CacherID,
z.RegionID,
z.Board,
21,
z.Points
FROM (SELECT CacherID,
gp.RegionID,
Board=gp.Board + 10,
( CASE
WHEN (SELECT COUNT(*)
FROM Geocache g
JOIN GeocacheRegions r
ON ( r.CacheID = g.ID )
WHERE r.RegionID = gp.RegionID
AND g.FinderPoints >= 5) < 20 THEN NULL
ELSE (SELECT SUM(y.FinderPoints) / 20
FROM (SELECT x.FinderPoints,
ROW_NUMBER() OVER (ORDER BY x.FinderPoints DESC, x.ID) AS Row
FROM (SELECT g.FinderPoints,
g.ID
FROM Geocache g
JOIN Log l
ON ( l.CacheID = g.ID )
JOIN Geocacher c
ON ( c.ID = l.CacherID )
JOIN GeocacheRegions r
ON ( r.CacheID = g.ID )
WHERE YEAR(l.LogDate) = @Year
AND g.FinderPoints >= 5
AND c.ID = gp.CacherID
AND r.RegionID = gp.RegionID) x) y
WHERE y.Row <= 20)
END ) Points
FROM GeocacherPoints gp
JOIN Region r
ON r.RegionID = gp.RegionID
WHERE gp.Control = 21
AND r.RegionType IN ( 'All', 'State' )
AND gp.Board = @Board - 10) z
WHERE z.Points IS NOT NULL
AND z.Points >= 1
ARITHABORT
經常被誤診為原因。
實際上從2005年版本開始ANSI_WARNINGS
開啟(因為它在你的兩個連接中) ARITHABORT
無論如何都是隱含的,並且這個設置沒有實際效果。
但它確實有副作用。 為了允許ANSI_WARNINGS
關閉的情況, ARITHABORT
的設置被用作計划緩存鍵之一,這意味着具有不同設置的會話不能共享彼此的計划。
當您在SSMS中運行查詢時,無法重用為您的應用程序緩存的執行計划,除非它們都具有相同的計划緩存密鑰,因此它會獲得一個新的計划,該計划會“嗅探”當前正在測試的參數值。 您的應用程序計划可能是針對不同的參數值編譯的。 此問題稱為“參數嗅探”。
您可以檢索並比較兩個執行計划
SELECT usecounts, cacheobjtype, objtype, text, query_plan, value as set_options
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
cross APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
where text like '%INSERT INTO GeocacherPoints (CacherID,RegionID,Board,Control,Points)%'
and attribute='set_options' and text not like '%this query%'
XML中的參數部分告訴您參數的編譯時間值。
請參閱應用程序中的慢速,SSMS中的快速? 更多地了解性能之謎 。
執行計划
您已經提供了估計的執行計划而不是實際的執行計划,但可以看出只有第一個查詢計划被參數化並且它是針對以下值編譯的。
<ParameterList>
<ColumnReference Column="@Dec31" ParameterCompiledValue="'2013-12-31'" />
<ColumnReference Column="@Jan1" ParameterCompiledValue="'2013-01-01'" />
<ColumnReference Column="@Board" ParameterCompiledValue="(71)" />
</ParameterList>
第二個執行計划使用變量而不是參數 。 這顯着改變了事情。
DECLARE @Board INT
DECLARE @Jan1 DATE
DECLARE @Dec31 DATE
SET @Board=71
SET @Jan1='January 1, 2013'
SET @Dec31='December 31, 2013'
INSERT INTO GeocacherPoints
SQL Server不會嗅探變量的特定值,並生成類似於使用OPTIMIZE FOR UNKNOWN
提示的通用計划。 該計划中的估計行數遠遠高於第一個計划中的行數。
你沒有說明哪個是快速計划,哪個是緩慢的計划。 如果使用變量的那個更快,那么您可能需要更新統計信息,您可能會遇到此處描述的問題統計,行估計和升序日期列如果使用參數的那個更快,那么您將能夠實現變量嗅探並獲得它通過使用OPTION (RECOMPILE)
提示來考慮實際變量值。
如果您使用的是SqlCommand並且沒有為CommandTimeout指定值,它將在30秒后自動超時。
這個問題似乎定期出現,這個鏈接位於列表的頂部: 查詢從Web應用程序中超時,但從管理工作室運行良好 。 ARITHABORT
肯定是罪魁禍首。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.