gpt4 book ai didi

c# - 在 C# Web 应用程序中插入查询超时,从 SQL Server Management Studio 运行正常

转载 作者:可可西里 更新时间:2023-11-01 07:57:41 26 4
gpt4 key购买 nike

我正在尝试让插入查询从我的 C# 网络应用程序中运行。当我从 SQL Server Management Studio 运行查询时,插入查询大约需要五分钟才能完成。从应用程序运行时,它会在三十分钟后超时(是分钟,而不是秒)。

我已经从 VS 调试器中获取了实际的 SQL 语句并从 Mgmt Studio 运行它,它工作正常。

所有这些都是在我的开发环境中运行的,而不是生产环境。查询正在进行时没有其他 SQL Server 事件。我正在使用 SQL Server 2008 R2 进行开发。 MS VS 2010 Express,Asp.Net 4.0。 SQL Server Mgmt Studio 10。

有一个从未回答过的类似问题:SQL server timeout 2000 from C# .NET

这是来自:dbcc useroptions 的 SET 选项

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

只有 textsize 和 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 的设置被用作 plan cache keys 之一。这意味着具有不同设置的 session 不能共享彼此的计划。

当您在 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 中的参数部分告诉您参数的编译时值。

参见 Slow in the Application, Fast in SSMS? Understanding Performance Mysteries了解更多。

执行计划

您提供了估计的执行计划而不是实际的执行计划,但可以看出只有第一个查询计划是参数化的,并且它是为以下值编译的。

        <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 的通用计划暗示。该计划中的估计行数远高于第一个计划。

您没有说明哪个是快速计划,哪个是慢速计划。如果使用变量的速度更快,那么您可能需要更新统计信息,您很可能会遇到此处描述的问题 Statistics, row estimations and the ascending date column如果使用参数的速度更快,那么您将能够实现变量嗅探,并通过使用 OPTION (RECOMPILE) 提示让它考虑实际变量值。

关于c# - 在 C# Web 应用程序中插入查询超时,从 SQL Server Management Studio 运行正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14145553/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com