2

こんにちは、ご清聴ありがとうございました。

質問の最初の背景:

IIS7で実行し、開発したASP.netアプリケーション全体で広く使用されているインラインテーブル関数があります。これは30以上のストアドプロシージャの基礎であり、その間、通常は最大200ミリ秒で処理されます(十分な速度以上)。アプリケーションは、すべてのデータベース接続に常に同じ接続文字列を使用します。関数自体は最大10msで実行されます。

関数が使用されているストアドプロシージャを呼び出すページを呼び出すと、15秒後にタイムアウトになる場合があります。このタイムアウトはページのすべてのユーザーに適用されますが、この関数を使用するストアドプロシージャもある他のページは、これが発生している間も正常に実行されます。これは、問題のある特定のストアドプロシージャであることを示しています。ただし、これは複数のページで発生しており、複数のストアドプロシージャまたは関数自体のいずれかであることを示しています。

Webアプリケーションでタイムアウトが発生している場合でも、異なるユーザークレデンシャルを使用してManagement Studioセッションからページ上のストアドプロシージャのいずれか(またはすべて)を実行すると、200ミリ秒未満になります。

関数でsp_recompileを実行すると、ログインクレデンシャルから常にタイムアウトが「クリア」されます。

これはアプリケーションの重要な部分であるため、sp_recompileはできるだけ早く実行され、デバッグに使用できる時間はほとんどありません。また、タイムアウトを自由に再現することはできませんでした。

私はインラインテーブル関数について多くの調査を試みましたが、これがそれらに共通の問題であることを示唆するものは何も見つかりませんでした。したがって、それらは避ける必要があります。

質問:

これらのタイムアウトが関数の使用によって引き起こされている可能性はありますか、それともそれに依存するストアドプロシージャの問題であることが保証されていますか?別の言い方をすれば、ビューを使用するように、または適切なロジックをインラインでカプセル化することによって、ストアドプロシージャをリファクタリングすることには、何らかの利点がありますか?

私の推測では、これはストアドプロシージャのみであり、不明なものの最適化を追加するか、必要に応じてオプションを再コンパイルするか、パラメータをローカライズすることでこれを解決する可能性がありますが、正直なところ、基礎となるものに適用される解決策を見つけたいと思います1つの場所で修正を適用できるように機能します。

関数:

CREATE FUNCTION [dbo].[fn_ObjectIDs] (
    @DateFrom       AS DATETIME = NULL
    ,@DateTo        AS DATETIME = NULL
    ,@Region        AS INT = NULL
    ,@FamilyID      AS INT = NULL
    ,@ParentID      AS INT = NULL
    ,@ChildID       AS INT = NULL
) RETURNS TABLE AS
RETURN
    SELECT DISTINCT
        obj.ID       AS IDs
    FROM tblObjects obj WITH (NOLOCK)
    INNER JOIN tblFamily fam WITH (NOLOCK)
            ON obj.famID = fam.famID
        LEFT JOIN tblCountry cntry WITH (NOLOCK)
            ON (@Region IS NOT NULL) AND (fam.countryId = cntry.countryId)
        LEFT JOIN tblParent parent WITH (NOLOCK)
            ON (@ParentID IS NOT NULL) AND (obj.ID = parent.objectID)
        LEFT JOIN tblChild child WITH (NOLOCK)
            ON (@ChildID IS NOT NULL) AND (obj.ID = child.objectID)
    WHERE
        obj.Visible = 1
        AND obj.statusID IN (3,4,6,8)
        AND ((@DateFrom IS NULL) OR (obj.CreatedDate >= @DateFrom))
        AND ((@DateTo IS NULL) OR (obj.CreatedDate <= @DateTo))
        AND ((@Region IS NULL) OR (cntry.regionID = @Region))
        AND ((@FamilyID IS NULL) OR (obj.famID = @FamilyID))
        AND ((@ParentID IS NULL) OR (parent.parentID = @ParentID))
        AND ((@ChildID IS NULL) OR (child.childID = @ChildID))
4

1 に答える 1

1

一時的にログを追加して、タイムアウトの問題の実際の原因を確認します。これは、アプリケーションとストアドプロシージャ自体で実行できます。プロシージャに、実行時にプロシージャを呼び出すために使用される現在のタイムスタンプとパラメータをログテーブルに書き込ませます。また、アプリケーションにロギングを追加します。次に、問題の原因となっている特定のパラメータがある場合、または問題が手順にまったく含まれていない場合に、特定のタイムアウトがいつ発生するかを特定できます。

一般に、ユーザー定義関数は良い考えではありませんが、私の理解では、テーブルインライン関数は他の関数よりも優れています。これにより多くのオーバーヘッドが追加され、オプティマイザはUDFで正しく機能しません。

于 2012-06-23T17:40:11.287 に答える