2017-05-31 16 views
0

に基づいて無視され、私はこの文SQL Serverの:インデックスが実行計画

UPDATE QP.LocalMessage WITH (UPDLOCK, ROWLOCK) 
SET StatusId = 0 
WHERE StatusId = 1 AND DateLockedUntil <= @DateNow 

を実行し、我々はすぐに

CREATE NONCLUSTERED INDEX [IX_LocalMessage_ProcessingLocked] 
    ON [QP].[LocalMessage] ([DateLockedUntil] ASC) 
    WHERE ([StatusId] = (1)) 

しかし、一見した後に実行するには、このアップデートのインデックスを作成したストアドプロシージャを持っています使用されている実行計画では、この索引を使用しておらず、代わりにクラスター索引スキャンを使用しています。これは、少なくとも2秒以下で実行されるこのステートメントを必要としますが、12-15秒に達する時刻が表示されます。私はなぜそれがインデックスを無視しているのか理解したいと思います。

+0

私は2つの理由を考えることができます。 1.ストアプロシージャは既にコンパイルされており、プランは格納されています(RECOMPILEを使用してテストできます)。2. SQL Serverは、そのインデックスを使用するとPKを使用するのと同じ時間がかかることがわかります。たぶんあなたは、そのインデックスに必要なフィールドを含めることができます – hardkoded

+2

質問:1)どのバージョンのSQL Server? 2)更新計画の実行計画の見積もりは何行ですか? 3)テーブルには何行ありますか? – RBarryYoung

答えて

2

非クラスタ化インデックスを使用する場合、SQL Serverはキー参照操作を行う必要があります。 select文では、これを回避することはできますが、これは避けることはできません。

述語によって返されるレコードの数が多い場合は、ノンクラスタード・インデックスのシークおよびキー・ルックアップよりもクラスタ・スキャンを実行する方がよいでしょう。

クエリがパラメータ化されているため、SQL Serverは返されるレコード数を確認できません。あなたはテーブル全体を更新することができます。

一部の実行ではレコードが数個しか更新されず、ノンクラスタード・インデックス・シークを使用できる場合は、「with recompile」句を使用してプロシージャを構成できます。これにより、SQL Serverは、プロシージャが受け取る各パラメータ値の計画を分析できます。別のオプションは、クエリで "option(recompile)"を使用することです。

ただし、更新されるレコードの数が少ない場合、SQL Serverはノンクラスタードインデックスのみを使用することに注意してください。

また、テーブル名以外に「(index = yourindexname)」をクエリヒントとして使用し、統計情報と統計情報を分析して、ノンクラスタードインデックスを使用したときの状態がどれほど悪いかを知ることができますクエリでそれを行うべきではありません。

+0

私はあなたがクエリを変更したと信じて、今はインデックスを使用しています。ステータスが1のレコードがあった開発環境でも、実行に1分かかりました。現在は1秒未満です。UPMATE LME WITH(UPDLOCK、ROWLOCK) SET StatusId = 0 \t FROM \t \t QP。LME WITH(UPDLOCK、ROWLOCK) \t INNER AS LocalMessageはONE.Id = LME.Id WHERE StatusId = ON ONEとして \t \t(StatusId = 1 \t \t QP.LocalMessage FROM \t \t \t SELECT ID)をJOIN 1 AND DateLockedUntil <= @DateNow – greektreat

2

include (StatusId)の場合、クエリでフィルタリングされたインデックスを使用できます。

CREATE NONCLUSTERED INDEX [IX_LocalMessage_ProcessingLocked_Include] 
    ON [QP].[LocalMessage] ([DateLockedUntil] ASC) 
    include (StatusId) 
    WHERE ([StatusId] = (1)) 

dbfiddle:http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=816af692f8993ce8844b5b5c7182f7a1


参考:

+0

参照していただきありがとうございます。同じstatusIdでフィルタリングされているため、インデックスを使用することがわかっています。それは良い読書でした。また、dbfiddleについて聞いたこともありません。それは素晴らしいようです!誰がこれを作ったの?また、内部結合を使用して変更を加えました。それはまだインデックスにインクルードのインクルードを使用するよりも速いようです。唯一の可能性のある問題は、テーブルのスプールです。レコードの数が多い場合は、パフォーマンスが低下する可能性があります。http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=5b860487035b466690e885c384a57550 – greektreat

+0

@greektreat Jack Douglas made dbfiddle.uk [新しいフィドルdba.se](https://dba.meta.stackexchange.com/q/2686/43889) – SqlZim

関連する問題