を使用するselect *
と、読み取りがはるかに少ないだけでなく、使用するよりも大幅に少ないCPU時間を使用するクエリがありますselect c.Foo
。
これはクエリです:
select top 1000 c.ID
from ATable a
join BTable b on b.OrderKey = a.OrderKey and b.ClientId = a.ClientId
join CTable c on c.OrderId = b.OrderId and c.ShipKey = a.ShipKey
where (a.NextAnalysisDate is null or a.NextAnalysisDate < @dateCutOff)
and b.IsVoided = 0
and c.ComplianceStatus in (3, 5)
and c.ShipmentStatus in (1, 5, 6)
order by a.LastAnalyzedDate
これは、主に表Bにある2,473,658の論理読み取りで終了しました。26,562CPUを使用し、期間は7,965でした。
これは生成されたクエリプランです。
PasteThePlan:https ://www.brentozar.com/pastetheplan/?id=BJAp2mQIQ
に変更c.ID
する*
と、クエリは107,049の論理読み取りで終了し、3つのテーブルすべてにほぼ均等に広がりました。4,266 CPUを使用し、期間は1,147でした。
これは生成されたクエリプランです。
PasteThePlan:https ://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ
私はこれらの結果と、ジョー・Obbishによって提案されたクエリヒントを使用しようとしました:
select c.ID
ヒントなし:https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID
ヒントと:https://www.brentozar.com/pastetheplan/ ?ID = B1W ___ N87
select *
ヒントなし:https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select *
ヒントと:https://www.brentozar.com/pastetheplan/?id=rJhhudNIQ
OPTION(LOOP JOIN)
ヒントを使用すると、ヒントのselect c.ID
ないバージョンに比べて読み取りの数が大幅に削減されましたが、それでもselect *
、ヒントのないクエリの約4倍の読み取りが行われています。クエリに追加するOPTION(RECOMPILE, HASH JOIN)
と、select *
他のどの試みよりもパフォーマンスが大幅に低下しました。
使用して表の統計とそのインデックスを更新した後WITH FULLSCAN
、select c.ID
クエリははるかに高速で実行されます。
select c.ID
更新前:https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select *
更新前:https://www.brentozar.com/ ?pastetheplan / ID = ryrvodEUX
select c.ID
:更新後https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select *
更新後:https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m
select *
select c.ID
合計継続時間と合計読み取りの点では依然として優れています(読み取りのselect *
約半分)が、より多くのCPUを使用します。全体として、更新前よりもはるかに近いですが、計画はまだ異なります。
同じ動作が、2014互換モードで実行されている2016年と2014年に見られます。2つの計画の不一致を説明できるものは何ですか?「正しい」インデックスが作成されていない可能性がありますか?統計がわずかに古いためにこれが発生する可能性がありますか?
述ON
部を結合の一部まで複数の方法で移動しようとしましたが、クエリプランは毎回同じです。
インデックスの再構築後
クエリに関係する3つのテーブルのすべてのインデックスを再構築しました。 c.ID
まだほとんどの読み取りを実行しています(2倍以上*
)が、CPU使用率は*
バージョンの約半分です。c.ID
またのソートにtempdbをこぼしたバージョンATable
:
c.ID
:https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
*
:https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ
また、並列処理なしで強制的に動作させてみたところ、最高のパフォーマンスのクエリが得られました:https : //www.brentozar.com/pastetheplan/?id=SJn9-vuLX
順序付けを行う大きなインデックスシーク後の演算子の実行カウントは、シングルスレッドバージョンでは1,000回しか実行されませんが、並列化バージョンでは2,622〜4,315回のさまざまな演算子の実行で大幅に増加しました。
select c.ID
はるかに高速クエリを、まだことをいくつかの余分な仕事をしているselect *
のヒントなしでクエリは、ありません。