web-dev-qa-db-ja.com

クエリストアが強制プランを尊重しない場合のプランの選択について

先週発生した、インシデント中に計画の退行を一時的に修正するために、クエリストアを使用して実行計画を強制したが、期待どおりに機能しないことがわかった状況を把握しようとしています。私はAndrew Kellyの記事を読みました forcedは常にforceを意味するわけではありません これは私が見ているものかもしれないと思いますが、私の場合のように、それについてもう少し洞察を期待しています計画は私が予想するよりももっと異なります。また、プランの強制に関する クエリストアのドキュメント のプランの強制に関する制限のセクションも確認しましたが、ここでの制限は適用されないと思います。

クエリストアのビューを以下に示します。8:30頃に、よりコストの高い新しいプランが表示され(2.14178と0.894238)、以前使用していたプランを強制しました。グラフからわかるように、古い計画を強制したにもかかわらず、新しい計画はこの時点からクエリのメトリックに対して表示されます。

query store forced plan

Sys.query_store_planを見ると、古いプランが強制として表示されており、それに対して何も失敗していないことがわかります。

![sys.query_store_plan

ここで奇妙なのは、後でプランキャッシュを調べたときに、これらのプランはどちらも使用されていなかったことです。ただし、使用中のプランは、上記のプラン13449と同じクエリプランハッシュ値を持っていますが、まったく異なります。実際に使用されているプラ​​ンの推定コストは72.6743とはるかに高かった。

これらの各プランからコンパイルされた値を取り、それらの3つに対してクエリを実行して、実際のメトリックがプランに対してどのように見えるかを理解しました。値は推定値とはかなり異なります。特に、キャッシュから取得したプランでは、別のインデックスを使用してデータを並べ替える必要があるため、約400 MBのメモリが付与されました。 3つのプランの推定コストは少し近かったが、クエリストアからの2つは、クエリストアに示されているプラ​​ンよりもはるかに高い推定コストでした。

これは、これが発生したクエリです。

(
    @id_group int,
    @create_date datetime,
    @rows_per_page int,
    @page_number int
)
SELECT *
FROM ts_customer
WHERE 
    id_group = @id_group 
    AND enabled = 'Y'
    AND (create_date >= @create_date)
ORDER BY 
    full_name, 
    id_customer desc
offset 
    ((@page_number - 1) * @rows_per_page) rows
    fetch next @rows_per_page rows only

なぜ計画が強制されなかったのか、なぜ使用中の計画がはるかに高価だったのかを誰かが私に理解するのを手伝ってくれませんか?

そんなこと知ってる select *は幅の広いテーブルであるため、大量のメモリが付与されますが、私は主にクエリストアでここに見られる動作を理解しようとしていますが、強制プランの代わりに使用されたプランでの理由を理解しようとしています。別のインデックスを使用し、並べ替えを行う必要がありました。

これが発生したデータベースは、Azure SQL DB、互換性レベル140で実行されており、従来のカーディナリティエスティメータを使用しています。

3つの推定プランすべてと、コンパイルされた値の各セットを使用してクエリを実行したときに生成されたプランを添付しました。これらにはアクセスできます ここ

6
PaulM

誰かが計画が強制されなかった理由を理解するのを手伝ってくれませんか

プランXMLを見ると、プランID 6194はSQL Serverのバージョン15.0。700.539でコンパイルされ、プランID 13449はバージョン15.0。900.210

2つの計画の(カーディナリティの推定値以外の)注意点の唯一の違いは次のとおりです。

計算スカラーは行の目標の影響を受けました(OFFSET / FETCHからの暗黙のTOPが原因):

EstimateRowsWithoutRowGoal="170.008"

そして、NLジョインは順不同のプリフェッチで最適化されました:

<NestedLoops Optimized="true" WithUnorderedPrefetch="true">

これらのわずかな違いが、あなたがリンクしたAndrew Kellyの記事で説明されている問題を引き起こしたようです。計画は基本的に同じですが、実装にわずかな違いがあります。 Grant Fritcheyは次のように説明しています。

「道徳的に同等な」計画、つまりすべての中核的な本質において同一であるが必ずしも完全に同一であるとは限らない計画を、定義した正確な計画の代わりに使用できる比較的あいまいな状況があります。ただし、これは一般的ではありません。

彼の473ページから 実行計画に関する無料の電子書籍

なぜ使用中のものははるかに高価だったのですか?

使用中の非常に高価なプランには4つの追加の列があるので、リンゴとリンゴを実際に比較しているのではないと思います。より高いコストは、主に使用されたパラメーター(したがって、より高い基数推定)が原因であると思われます。ちなみに、それは別の完全に異なるビルドです:15.0。1300.566。物事は確実にクラウドで高速に移動します= P

これらはすべてSELECT *からの「新しい」列です。

<ColumnReference Database="[app-live-au]" Schema="[dbo]" Table="[ts_customer]" Column="delete_requested_date_utc" />
<ColumnReference Database="[app-live-au]" Schema="[dbo]" Table="[ts_customer]" Column="retention_policy_applied_date_utc" />
<ColumnReference Database="[app-live-au]" Schema="[dbo]" Table="[ts_customer]" Column="retention_policy_type" />
<ColumnReference Database="[app-live-au]" Schema="[dbo]" Table="[ts_customer]" Column="id_portal_user" />

あなたが提供した組み合わせテストは、すべてこの最新バージョンのものと一致していました。

3
Josh Darnell