SQLフィドル:http ://sqlfiddle.com/#!3/23cf8
このクエリではIn
、Idに句があり、他の列も選択すると、最初にInが評価され、次に、RIDルックアップを介してDetails列と他の列が取得されます。
--In production and in SQL Fiddle, Details is grabbed via a RID Lookup after the In clause is evaluated
SELECT [Id]
,[ForeignId]
,Details
--Generate a numbering(starting at 1)
--,Row_Number() Over(Partition By ForeignId Order By Id Desc) as ContactNumber --Desc because older posts should be numbered last
FROM SupportContacts
Where foreignId In (1,2,3,5)
このクエリでは、詳細はテーブルスキャンを介して取得されます。
With NumberedContacts AS
(
SELECT [Id]
,[ForeignId]
--Generate a numbering(starting at 1)
,Row_Number() Over(Partition By ForeignId Order By Id Desc) as ContactNumber --Desc because older posts should be numbered last
FROM SupportContacts
Where ForeignId In (1,2,3,5)
)
Select nc.[Id]
,nc.[ForeignId]
,sc.[Details]
From NumberedContacts nc
Inner Join SupportContacts sc on nc.Id = sc.Id
Where nc.ContactNumber <= 2 --Only grab the last 2 contacts per ForeignId
;
SqlFiddleでは、2番目のクエリは実際にRIDルックアップを取得しますが、100万レコードの本番環境では、テーブルスキャンが生成されます(IN
句は行の99%を削除します)
それ以外の場合、SQL Fiddleに表示されるクエリプランは同じです。唯一の違いは、2番目のクエリのSQL FiddleのRIDルックアップは、本番環境でのテーブルスキャンです:(
この動作を引き起こす可能性を理解したいですか?ここでテーブルスキャンを使用して原因を特定するために、どのようなことを検討しますか?
そこでRIDルックアップを使用するように影響を与えるにはどうすればよいですか?
実際の実行プランで運用コストを見ると、RIDルックアップを使用できるようになれば、2番目のクエリのパフォーマンスを最初のクエリに非常に近づけることができると思います。列を選択しない場合Detail
、両方のクエリのパフォーマンスは本番環境で非常に近くなります。そのような他の列を追加した後でのみDetail
、2番目のクエリのパフォーマンスが大幅に低下します。それをSQLFiddleに入れて、実行プランがRIDルックアップを使用していることを確認したとき、私は驚きましたが、少し混乱しました...
異なるクラスター化インデックスを使用したテストでは、このクエリや他のクエリのパフォーマンスがわずかに低下したため、クラスター化インデックスはありません。それは私が他の列を追加し始める前Details
でした、そして私はそれをもっと実験することができます、しかし私がランダムなインデックスで暗闇の中で撮影を始める前に今何が起こっているのかを理解したいと思います。