「時々」遅いクエリの診断に関するアドバイス


20

カバリングインデックスを介してインデックス付きビューから結果を返すストアドプロシージャがあります。通常、高速(約10ミリ秒)で実行され、最大8秒まで実行されることもあります。

ランダム実行の例を次に示します(注:これは低速ではありませんが、クエリテキストは、渡される値を除いて同じです)。

declare @p2 dbo.IdentityType
insert into @p2 values(5710955)
insert into @p2 values(5710896)
insert into @p2 values(5710678)
insert into @p2 values(5710871)
insert into @p2 values(5711103)
insert into @p2 values(6215197)
insert into @p2 values(5710780)

exec ListingSearch_ByLocationAndStatus @statusType=1,@locationIds=@p2

スプロックは次のとおりです。

ALTER PROCEDURE [dbo].[ListingSearch_ByLocationAndStatus]
    @LocationIds IdentityType READONLY,
    @StatusType TINYINT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT      -- lots of fields
    FROM        [dbo].[ListingSearchView][a] WITH (NOEXPAND)
    INNER JOIN  @LocationIds [b] ON [a].[LocationId] = [b].[Id]
    WHERE       [a].[StatusType] = @statusType
    OPTION (RECOMPILE);

(注:OPTION (RECOMPILE)いくつかのアドバイスの後に最近ヒントを追加しましたが、助けにはなりませんでした。

カバーインデックスは次のとおりです(注:ビューには、ListingId一意のクラスター化インデックスもあります)

CREATE NONCLUSTERED INDEX [IX_ListingSearchView_ForAPI] ON [dbo].[ListingSearchView]
(
    [LocationId] ASC,
    [StatusType] ASC
)
INCLUDE ( -- all the fields in the query) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

showplan XML統計を使用して、プロファイラートレースを配置します。

遅いもの(6秒)と関連する計画は次のとおりです。 ここに画像の説明を入力してください

私が期待するとおりに見え、クエリが高速の場合と同じ計画です。

計画の費用のかかる部分を拡大すると、次のようになります。 ここに画像の説明を入力してください

ビュー/バッキングテーブルの完全なスキーマを次に示します(それが役立つ場合):https : //pastebin.com/wh1sRcbQ

ノート:

  • インデックスはデフラグされており、統計は最新です。
  • もともとクエリはビューに対してインラインでしたが、安定させるためにSPROCに移動しました。助けていない。
  • WITH OPTION (RECOMPILE);ヒントの追加(機能しなかったので、パラメータスニッフィングはできませんか?)
  • システム内の他のクエリも実行が遅い場合があり、計画にも明らかな問題はありません。
  • ロックできますか?確認方法がわからない。

次に試すことができるアイデアはありますか?

ありがとう


1
コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました全員:この質問の詳細については、その機能を使用してください。
ポールホワイトはGoFundMonicaを言う

リンクではないworking.procクエリはまっすぐ、concern.Iの面積である行の実際と推定数の間に大きな差分があるされて与えられたビューquery.Iで問題の嘘が不十分data.Itは近いはずだと思うだと思う
KumarHarsh

クエリの実行中にWhoIsActive(Adam Machanic作)を実行しようとしましたか?whoisactive.comこれには、待機中のタスクに関する情報が含まれており、正しい方向を示すことができます。
MJH

これを引き起こすDBの外部の何かを削除しましたか。おそらく、DBと共有されているストレージへの同期IOを引き起こす他のアプリケーションがありますか?
ヨハン

回答:


2

を使用することOPTION (RECOMPILE)は、パラメータスニッフィングの可能性を排除する効果的な方法だとは本当に思いません。

パラメータースニッフィングは、SQLが特定のクエリについて混乱し、新しいパラメーターを検出したために新しいと判断した場合に発生します。新しい実行計画を生成するのに余分な時間がかかるため、時間がかかります。

そのオプションは、SQLが毎回新しいプランを作成するように強制しますが、これはほぼ同じことです。代わりに、次のヒントを使用してデフォルトパラメータを追加することを検討してください。

OPTION(OPTIMIZE FOR(@LocationIds='xx',@StatusType='xx'))

デフォルトのパラメーターを選択するときは、統計的に代表的なセットを使用してください。
これにより、毎回同じプランが強制的に使用され、パラメータスニッフィングの可能性が排除されます。一度それを行い、それが役に立たなかったと判断したら、パラメータスニッフィングを可能性として無視しても安全でしょう。


1

おそらく、順序を強制しようとするので、常に小さなテーブル(変数)から開始することになります。しかし、ビューでは注意が必要です...

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    OPTION (FORCE ORDER);

または、テーブル変数をビューに結合する一般的な方法である場合、ループ結合を強制することができます。これは順序を強制します...

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER LOOP JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    --leaving this here so you don't get an annoying warning 
    OPTION (FORCE ORDER);

0

クエリエディターでストアプロシージャの名前を書き、ストアプロシージャを選択します。名前を入力してから、推定実行プランの表示を選択するか、(Ctrl + L)をクリックします。この画像の下。

推定実行計画の表示の画像

クエリエディターの下部にある[メッセージ]タブのすぐ横に実行計画が表示されます。次に、緑色の線に欠落しているインデックスの詳細が表示され、それを右クリックします。次に、新しいタブで新しいクエリを開き、インデックスを作成します。その後、クエリは高速に実行されます。

そのため、このメソッドを使用して、クエリの診断に時間がかかります。また、使用できるクエリまたはメソッドが非常に多くあります。

詳細を含む実行計画


-1

問題がブロッキングにあると思われる場合は、楽観的なトランザクション分離レベルRead Committed Snapshotを使用することをお勧めします(これにより、tempDBにオーバーヘッドがかかることに注意してください)。

リファレンス: https : //docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server

問題が読み取り/書き込みブロッキングにない場合は、ビューにインデックスを追加してみてください(インデックスの最適な選択は、データの選択性に依存します)

CREATE NONCLUSTERED INDEX IX_ListingSearchView (LocationID, StatusType) INCLUDE (other columns...)

1
提案するインデックスは既に存在しますIX_ListingSearchView_ForAPI(質問のスクリプトを参照)。
ポールホワイトはGoFundMonicaを言う

1
ねえ、答えてくれてありがとう。しかし、私の質問で言ったように、修正を適用する前に問題が何であるかを知りたいです。それ以外の場合は、実際の問題を見落としている可能性があります。私の質問は、最初に問題を見つけ、次に正しい解決策を見つけることです。
RPM1984

ローカル環境でその遅いクエリを取得できますか?同じクエリが時々遅く実行され、時には速く実行される場合、入力パラメータに依存する可能性があります。遅いクエリによって返される論理読み取りの数と行の総数を教えてください。
アルタッシュハチャトリアン

@ArtashesKhachatryanはい、ローカルでも動作が遅い場合があります。実行計画で質問を更新しました。あなたが言ったように、それは遅いクエリが速いクエリよりも多くの行を返すことに関連しているのだろうかと思っています。
RPM1984
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.