0

私のウェブサイトから(ウェブサイト接続プールを介して)呼び出されると時々タイムアウトするストアドプロシージャがあります。タイムアウトになると、ManagementStudioセッションからdrop/ createまたはsp_recompileを使用してプロシージャが再コンパイルされるまで、常にタイムアウトにロックされます。

タイムアウトしている間は、ManagementStudioを使用した同じ手順で同じパラメーターを使用してタイムアウトすることはありません。

Management Studioを介して「ALTERPROCEDURE」を実行し、(かなり大幅に)プロシージャの内部実行を変更しても、タイムアウトはクリアされませんでした。完全なsp_recompileが実行されるまでクリアされませんでした。

ストアドプロシージャはで終了しますOPTION (RECOMPILE)

このプロシージャは2つの関数を呼び出します。これらの関数は、製品の残りの部分全体で広く使用されています。これらの機能を(同様の方法で)使用する他の手順は、問題の手順がタイムアウトしている期間中であっても、すべて機能します。

誰かがこのタイムアウトを引き起こしている可能性があるものについてさらにアドバイスを提供することができれば、それは大いにありがたいです。

ストアドプロシージャは次のとおりです。

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
4

1 に答える 1

2

実行するたびに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で問題が解決せず、最後のクエリを削除しても問題が解決しない場合は、データの収集に使用するテーブル関数を確認する必要があります。

于 2012-07-19T09:54:49.330 に答える