関数呼び出しによる推定クエリプランと実際のクエリプラン


11

SQLサーバーにこのクエリがあります。マージレプリケーションクエリです。

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

推定クエリプランには、3つのクエリに関する情報が含まれます。

  1. 上記のクエリ
  2. fn_MSgeneration_downloadonlyへの関数呼び出し
  3. fn_MSArticle_has_downloadonly_propertyへの関数呼び出し

実際のクエリプランには、次の情報のみが含まれます。

  1. 上記のクエリ

関数については何もありません。実際のプランで機能情報が欠けているのはなぜですか?

私はこれらのオプションを試しました:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

実際のプランを作成しましたが、Management Studioで実際のクエリプランオプションを使用したときと同じように、パート2と3が欠落していました。

たとえば、プロファイラーを使用して関数呼び出しに関する情報を取得する場合、どのイベントを選択しますか?


クエリプランに特に関連する回答は見つかりませんでしたが、SP:StmtStartingおよびSP:StmtCompletedのプロファイルを作成したところ、関数呼び出しが表示されました。

回答:


17

そして機能については何も。実際のプランで機能情報が欠けているのはなぜですか?

これは、パフォーマンス上の理由から、仕様によるものです。

定義に含まれている関数はBEGINEND入力行ごとに新しいT-SQLスタックフレームを作成します。別の言い方をすると、関数本体は入力行ごとに個別に実行されます。この単一の事実は、T-SQLスカラー関数および複数ステートメント関数に関連するほとんどのパフォーマンスの問題を説明します(インラインテーブル値関数はBEGIN...END構文を使用しないことに注意してください)。

あなたの質問の文脈では、これはSHOWPLAN各行の完全な出力になります。XMLプランの出力は非常に冗長であり、作成にコストがかかるため、すべての行について完全な出力を作成することは、一般的には悪い考えです。

以下のT-SQLスカラー関数を考えます。これは、AdventureWorksサンプルデータベースで作成され、IDを指定すると製品の名前を返します。

CREATE FUNCTION dbo.DumbNameLookup
(
    @ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
    RETURN
    (
        SELECT
            p.Name
        FROM Production.Product AS p
        WHERE
            p.ProductID = @ProductID
    );
END;

実行前計画

実行前計画(SSMSの推定計画)は、親ステートメントとネストされた関数呼び出しの計画情報を示します。

-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;

SSMS出力:

SSMS実行前計画

SQL Sentry Plan Explorerで表示される同じXML は、呼び出しのネストされた性質をより明確に示しています。

PE実行前計画

実行後の出力

SSMSは、実行後の計画の出力が要求されたときに、メインクエリのみの詳細を表示します。

-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;

SSMS実行後

それ以外の場合のパフォーマンスへの影響は、SQL Server Profiler のShowplan XML Statistics Profileイベントクラスを使用して、関数を複数回呼び出すクエリ(入力行ごとに1回)を使用して表示できます。

SELECT TOP (5)
    p.ProductID,
    dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;

プロファイラーの出力:

トレース出力

関数の実行には5つの個別の実行後プランがあり、1つは親クエリ用です。5つの関数プランは、プロファイラーの下部ペインで次のようになります。

機能計画

親クエリプランは次のとおりです。

親計画

TOP (5)句なしでクエリを実行すると、Productテーブルの504行ごとに完全な実行プランが作成されます。おそらく、これが大きなテーブルですぐに手に負えなくなることがわかるでしょう。

トリガーの状況は逆になります。これらには実行前の計画情報は表示されませんが、実行後の計画は含まれます。これは、トリガーのセットベースの性質を反映しています。行ごとに1回ではなく、影響を受けるすべての行に対して1回ずつ発生します。


@PaulWhite推定実行プランを要求するときにトリガープランが表示されない理由はありますか?これは欠けている便利な機能のようです。そのための接続アイテムを作成する場合があります。
usr

@usr-選択された実際のキャッシュされたプランは、ここで説明されているように実際の行数によって異なる可能性があるためでしょうか?technet.microsoft.com/en-us/library/…–
マーティン・スミス

理由かもしれない@MartinSmith。最近、checkおよびfk制約の実行プランの接続アイテムに完了のマークが付けられたので、トリガーで同じことを行うと期待していました。
usr

@usr- これはここですか?3ヶ月?これは、新機能のリクエストの記録的な好転に違いありません。
Martin Smith

@MartinSmithはい、それ。1〜2年前に修正されました。クエリストアをクエリする必要がないことを本当に望んでいます。SSMSのボタンをクリックしたいと思っていました。実際、何年も触れられなかったエンジン部分の変化に驚いた。しかし、おそらく何もありませんでした。
usrは
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.