我有一个存储过程,当从我们的网站(通过网站连接池)调用时,它偶尔会超时。一旦超时,它总是被锁定到超时,直到使用drop/create或sp_recomplete从Management Studio会话重新编译该过程。
当超时时,对于使用Management Studio的相同过程,使用相同的参数不会超时。
通过Management Studio执行"ALTER PROCEDURE"并(相当大的幅度)更改该过程的内部执行并没有清除超时-只有运行完整的sp_recomplete才能清除超时。
存储过程以OPTION (RECOMPILE)
结束
该过程调用两个函数,这两个函数在产品的其余部分中普遍使用。使用这些功能(以类似方式)的其他程序都有效,即使在相关程序超时的时期也是如此。
如果有人能就这次休假的原因提供任何进一步的建议,我们将不胜感激。
存储过程如下:
ALTER PROCEDURE [dbo].[sp_g_VentureDealsCountSizeByYear] (
@DateFrom AS DATETIME = NULL
,@DateTo AS DATETIME = NULL
,@ProductRegion AS INT = NULL
,@PortFirmID AS INT = NULL
,@InvFirmID AS INT = NULL
,@SpecFndID AS INT = NULL
) AS BEGIN
-- Returns the stats used for Market Overview
DECLARE @IDs AS IDLIST
INSERT INTO @IDs
SELECT IDs
FROM dbo.fn_VentureDealIDs(@DateFrom,@DateTo,@ProductRegion,@PortFirmID,@InvFirmID,@SpecFndID)
CREATE TABLE #DealSizes (VentureID INT, DealYear INT, DealQuarter INT, DealSize_USD DECIMAL(18,2))
INSERT INTO #DealSizes
SELECT vDSQ.VentureID, vDSQ.DealYear, vDSQ.DealQuarter, vDSQ.DealSize_USD
FROM dbo.fn_VentureDealsSizeAndQuarter(@IDs) vDSQ
SELECT
yrs.Years Heading
,COUNT(vDSQ.VentureID) AS Num_Deals
,SUM(vDSQ.DealSize_USD) AS DealSize_USD
FROM tblYears yrs
LEFT OUTER JOIN #DealSizes vDSQ ON vDSQ.DealYear = yrs.Years
WHERE (
((@DateFrom IS NULL) AND (yrs.Years >= (SELECT MIN(DealYear) FROM #DealSizes))) -- If no minimum year has been passed through, take all years from the first year found to the present.
OR
((@DateFrom IS NOT NULL) AND (yrs.Years >= DATEPART(YEAR,@DateFrom))) -- If a minimum year has been passed through, take all years from that specified to the present.
) AND (
((@DateTo IS NULL) AND (yrs.Years <= (SELECT MAX(DealYear) FROM #DealSizes))) -- If no maximum year has been passed through, take all years up to the last year found.
OR
((@DateTo IS NOT NULL) AND (yrs.Years <= DATEPART(YEAR,@DateTo))) -- If a maximum year has been passed through, take all years up to that year.
)
GROUP BY yrs.Years
ORDER BY Heading DESC
OPTION (RECOMPILE)
END
如果您想在每次执行SP时重新编译它,您应该用recompile声明它;您的语法只重新编译最后一个选择:
ALTER PROCEDURE [dbo].[sp_g_VentureDealsCountSizeByYear] (
@DateFrom AS DATETIME = NULL
,@DateTo AS DATETIME = NULL
,@ProductRegion AS INT = NULL
,@PortFirmID AS INT = NULL
,@InvFirmID AS INT = NULL
,@SpecFndID AS INT = NULL
) WITH RECOMPILE
我不知道你手术的哪一部分会引起问题。您可以试着注释掉选择的部分,看看从表函数创建临时表是否会产生性能问题;如果没有,那么查询本身就是一个问题。您可以重写过滤器如下:
WHERE (@DateFrom IS NULL OR yrs.Years >= DATEPART(YEAR,@DateFrom))
AND (@DateTo IS NULL OR yrs.Years <= DATEPART(YEAR,@DateTo))
或者,也许更好的方法是,声明startYear和endYear变量,相应地设置它们,并更改如下位置:
declare @startYear int
set @startYear = isnull (year(@DateFrom), (SELECT MIN(DealYear) FROM #DealSizes))
declare @endYear int
set @endYear = isnull (year(@DateTo), (SELECT MAX(DealYear) FROM #DealSizes))
...
where yrs.Year between @startYear and @endYear
如果WITH RECOMPILE不能解决问题,并且删除最后一个查询也没有帮助,那么您需要检查用于收集数据的表函数。