web-dev-qa-db-ja.com

SQL Sentry Plan ExplorerはUDFの読み取りをカウントしますか?

私はこのようなクエリを持っています:

select dbo.fn_complexFunction(t.id)
from mytable t

SQL Sentry Plan Explorerで、クエリプランにUDFを含めるには、SQL SentryでGet Estimated Planを実行する必要があることに気付きました。

「実際のプランを取得」を実行すると、論理読み取りやその他のメトリックにUDFで発生する操作が含まれているように見えません。このような場合、プロファイラーを使用する唯一の回避策はありますか?

9
Gabe

明らかな免責事項:私は SQL Sentryのために働きます

私たちが抱えている最大の問題は次のとおりです。

  1. @JNKが言うように、SQL ServerはUDFの使用を難読化し、とにかくひどいことをします(常に1行を推定するように)。 SSMSで実際のプランを生成しても、その使用法はまったくわかりません。 SQL Serverが提供するプランに関する情報しか提供できないため、同じ制限を受けます。
  2. 実際の計画を生成する際、ランタイムメトリックのさまざまなソースに依存しています。残念ながら、プランXMLには関数呼び出しが含まれておらず、SQL ServerはSET STATISTICS IO ON;の使用時に関数によって発生したI/Oを明らかにしません(これがTable I/Oタブに入力する方法です)。

AdventureWorks2012に対する次のビューと機能を検討してください。これは、ヘッダーテーブルからランダムな行が与えられた場合、詳細テーブルからランダムな行を返すというばかげた試みです。ほとんどの場合、毎回可能な限り多くのI/Oを生成するためです。

CREATE VIEW dbo.myview 
WITH SCHEMABINDING
AS
  SELECT TOP (100000) rowguid, SalesOrderID, n = NEWID() 
    FROM Sales.SalesOrderDetail ORDER BY NEWID();
GO

CREATE FUNCTION dbo.whatever(@SalesOrderID INT)
RETURNS UNIQUEIDENTIFIER
WITH SCHEMABINDING
AS
BEGIN
  RETURN 
  (
    SELECT TOP (1) rowguid FROM dbo.myview 
     WHERE SalesOrderID = @SalesOrderID ORDER BY n
  );
END
GO

Management Studioが行うこと(および行わないこと)が示すこと

SSMSで次のクエリを実行します。

SET STATISTICS IO ON;

  SELECT TOP (5) SalesOrderID, dbo.whatever(SalesOrderID) 
    FROM Sales.SalesOrderHeader ORDER BY NEWID();

SET STATISTICS IO OFF;

プランを見積もるとき、あなたは クエリのプランを取得しますand a single関数のプラン (ご希望のように5ではありません) :

Estimated plan in Management Studio

クエリが実際に実行されなかったため、I/Oデータをまったく取得しません。次に、実際の計画を生成します。結果グリッドで期待した5行を取得します 次の計画 (これは、クエリテキストの一部として、および一部として見つけることができるXMLを除いて、UDFについて目に見える言及をまったく行いません)スカラー演算子の)):

Actual plan in Management Studio

そして、次のSTATISTICS IO出力(これはSales.SalesOrderDetailについてまったく言及していませんが、そのテーブルから読み取るにはhadです):

テーブル 'SalesOrderHeader'。スキャンカウント1、論理読み取り57、物理読み取り0、先読み読み取り0、LOB論理読み取り0、LOB物理読み取り0、LOB先読み読み取り0。

プランエクスプローラーが教えてくれること

同じクエリの推定プランを生成すると、SSMSと同じことがわかります。ただし、少し直感的な方法で表示します。たとえば、外部クエリの推定プランは、関数の出力がクエリの出力とどのように組み合わされるかを示し、 単一のプランダイアグラム内で、両方からI/Oがあることがすぐにわかります)テーブル

Estimated plan in Plan Explorer

また、 関数のプランを単独で表示する も、完全を期すためにのみ含めています。

Estimated plan for UDF in Plan Explorer

それでは、実際の計画を見てみましょう。これは、数千倍も有用です。ここでも欠点は、SQL Serverが表示することを決定した情報しかないため、SQL Serverから提供されるグラフィカルなプラン図のみを公開できることです。これは、有用な情報を表示しないことを決定した状況ではありません。提供されているプラ​​ンXMLに基づいて、実際にそれについて何も知りません。この場合、SSMSと同様です 外部クエリのプランのみが表示され、関数がまったく呼び出されていないように見えます

Actual plan in Plan Explorer

[テーブルI/O]タブも同様に、STATISTICS IO の出力に依存しています。これにより、関数呼び出しで実行されるアクティビティもすべて無視されます。

Table I/O for actual plan in Plan Explorer

ただし、コールスタック全体を取得します。 「Pffft、いつコールスタックが必要になるのか」という質問をときどき耳にしました。実際に 費やした時間、使用されたCPU、および読み取りの数(およびTVFの場合は生成された行の数)をすべての1つ関数呼び出し に分解できます。

Call stack in Plan Explorer, showing UDF calls

残念ながら、I/Oの送信元のテーブルに関連付けることはできません(ここでも、SQL Serverはその情報を提供しないため)、UDF名でラベル付けされていません(これは、関数呼び出し自体ではなく、アドホックステートメントとしてキャプチャされるためです)。しかし、Management Studioではできないことを見ることができるのは、UDFがどんな犬なのかです。まだいくつかのドットを結合する必要がありますが、ドットの数は少なく、それらはより近くにあります。

プロファイラについて

最後に、UIツールのスコープ外で実行するサーバー側のトレースを設定する場合を除いて、Profilerから離れることを強くお勧めします。 プロファイラーを本番システムに対して使用すると、ほぼ確実に、これまでに解決されるよりも多くの問題が発生します 。この情報を取得したい場合は、サーバー側のトレースまたは拡張イベントを使用し、非常に賢くフィルタリングしてください。プロファイラーがなくても、トレースがサーバーに影響を与える可能性があります 拡張イベントを通じてショープランを取得することも、世界で最も効率的な方法ではありません

11
Aaron Bertrand