OPTION FORCE ORDERにより、行が削除されるまでパフォーマンスが向上します


9

やや複雑なSQL Server 2008クエリ(約200行のかなり高密度のSQL)があり、必要なときに実行されませんでした。時間の経過とともに、パフォーマンスは約0.5秒から約2秒に低下しました。

実行計画を見ると、結合を並べ替えることでパフォーマンスが向上することは明らかでした。私はそうしました、そしてそれは...約0.3秒にまで減少しました。これで、クエリに「OPTION FORCE ORDER」というヒントが追加されました。

今日、私はデータベースをクリーンアップします。行の約20%をアーカイブし、行を削除する以外は関連するデータベースでアクションを実行しません...実行プランは完全にホースされます。特定のサブツリーが返す行数を完全に誤って判断し、(たとえば)次のものを置き換えます。

<Hash>

<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>

これで、クエリ時間が約0.3秒から約18秒に急上昇します。(!)行を削除したからといって。クエリヒントを削除すると、クエリ時間は約2秒に戻ります。良いが悪い。

データベースを複数の場所とサーバーに復元した後、問題を再現しました。各テーブルから行の約20%を削除するだけで、常にこの問題が発生します。

  1. 強制結合順序がクエリの見積もりを完全に不正確にする(したがってクエリの時間を予測できない)のは、これが正常ですか?
  2. 最適ではないクエリのパフォーマンスを受け入れる必要があるか、それともタカのように見て、頻繁に手動でクエリのヒントを編集する必要があると思いますか?または、すべての結合についてもヒントがありますか?.3sから2sは大ヒットです。
  3. 行を削除した後にオプティマイザが停止した理由は明らかですか?たとえば、「はい、サンプルスキャンを実行しました。データ履歴の前半でほとんどの行をアーカイブしたため、サンプルはスパースな結果を生成したため、ソートされたハッシュ演算の必要性を過小評価していました」

実行計画を見たい場合は、投稿できる場所を提案してください。そうでなければ、私は最も素晴らしいビットをサンプリングしました。これが根本的な誤推定です。括弧内の数字は(推定:実際の)行です。

                             /  Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
                             \  NonClustered Index Seek (1:7229)

内部ループは908行をスキャンすると予想されますが、代わりに52,258,441をスキャンすることに注意してください。正確であれば、このブランチは12秒ではなく、約2ミリ秒で実行されたはずです。行を削除する前に、この内部結合の推定は合計係数2だけオフであり、2つのクラスター化インデックスのハッシュ一致として実行されました。

回答:


6

強制結合順序がクエリの見積もりを完全に不正確にする(したがってクエリの時間を予測できない)のは、これが正常ですか?

FORCE ORDERを使用しても推定値が不正確になることはありません。行を削除した場合と同様です。テーブルの統計を強制的に更新すると、推定精度が向上する場合があります。

最適ではないクエリのパフォーマンスを受け入れる必要があるか、それともタカのように見て、頻繁に手動でクエリのヒントを編集する必要があると思いますか?または、すべての結合についてもヒントがありますか?.3sから2sは大ヒットです。

FORCE ORDERヒントを使用せずに、最適化計画に最適な計画を生成するために必要な情報が提供されるようにすることが望ましいでしょう。そうすることで、手作業による介入を必要とせずに、基礎となるデータ配布への変更にうまく対処できるはずです。ただし、データの性質によってカーディナリティが1時間ごとまたは1日ごとに大幅に変化する可能性がある場合は、計画ガイドを使用して計画が確実に修正されるようにすることを検討してください

行を削除した後にオプティマイザが停止した理由は明らかですか?たとえば、「はい、サンプルスキャンを実行しました。データ履歴の前半でほとんどの行をアーカイブしたため、サンプルはスパースな結果を生成したため、ソートされたハッシュ演算の必要性を過小評価していました」

問題のあるテーブルの行数については言及しませんでしたが、削除によって次のいずれかになる可能性があります。

  • 統計の更新をトリガーするのに十分な行を削除しませんでした。これは、行の20%が変更されたときに発生するはずですが、動的しきい値を有効にするためにトレースフラグ2371を使用するオプションがあります。
  • 統計の更新をトリガーしましたが、収集されたサンプルは代表的なものではありませんでした。これを修正するには、WITH FULLSCANを使用して手動更新を実行します。

また、無数のオプションを回避できる古き良きパラメータスニッフィングの問題が発生している可能性もあります。WITH RECOMPILEは、クエリでこれほど大きな値を指定するにはコストのかかるオプションですが、プロシージャレベルとステートメントレベルの両方で調査する価値があります。


ただ説明すると、それはおそらく意味論です:「FORCE ORDERの使用は推定を不正確にしていない、行の削除はそうでした。」では、「FORCE ORDER」を削除することでクエリが大幅に改善されたのは偶然だと思いますか?ヒントはオプティマイザをあまり重視せずに統計に依存するようにしませんでしたか、またはこの信頼性の低い統計がめったに重要ではないため、アプリケーションテストで発見されませんでしたか?
シャノン2012

オプティマイザが優先する計画の選択はたまたま不正確な統計に対処しますが、結合順序が強制された結果として生じた計画はそうではないので、そうだと思います。私はFORCE ORDERが統計評価に変化をもたらすことを知りませんが、反対のことがわかっている場合は誰かがチャイムを鳴らします。また、OPTIMIZE FORに選択した値が適切かどうかも考慮する必要があります。統計は絶対に問題ないが、代表的ではない値に基づいて計画を強制している可能性があります。
Mark Storey-Smith

正しい。私はそれらを最適化したのとまったく同じようにパラメーターを渡すと同じパフォーマンスの問題があります。再度、感謝します。
シャノン2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.