web-dev-qa-db-ja.com

クエリメモリの付与とtempdbの流出

CEが実際の行数に非常に近い(微調整後)にもかかわらず、tempdbに波及する長時間実行されているクエリ(1億行が多数の小さな薄暗いテーブルを結合し、次にグループ化するクエリ)があります。計画を参照してください。 :

enter image description here

説明を探していると、次のメモリ許可情報に気づきました。

enter image description here

環境:SQL Server 2012 SP1 Enterprise、サーバーRAM 256 GB、SQL Serverの最大メモリ200 GB、バッファープールサイズ42 GB、ワークスペースの最大サイズ156 GB(GrantedMemory = 156 * 25%〜= 38 GB)

ご質問

  1. これは、CEがどれほど優れていても、クエリがこぼれない可能性がないことを意味しますか?クエリの最大RAMが38 GBにハードキャップされているため
  2. クエリオプティマイザーは、プランを作成するときに最大クエリRAMを考慮しませんか? (ハッシュマッチ集約を強制すると、並べ替え手順が不要になり、クエリのパフォーマンスが大幅に向上します。残念ながら、実際のクエリはCognosからのものであり、制御することはできません。)
  3. ここで、25%の上限を100%に近づけるのが賢明なオプションでしょうか? (前述のサーバーアクセスを制御して、同時クエリ要求の数を制限できると仮定)

匿名化されたクエリプラン Paste The Plan

(ソート+ストリーム集計ではなく)ハッシュ一致集計を強制すると、クエリは常に3〜4倍速く終了します。残念ながら、実際のクエリはCognosからのものであり、変更する方法はありません。

ハッシュ集計計画にはハッシュ流出はありません。クエリオプティマイザーはハッシュ一致集計を選択しません。これは、ハッシュとストリーム集計の演算子コストを見ると、ハッシュグループのCPUコストがストリーム集計の2〜3倍であるためです。

ストリーム集計とハッシュ集計の両方で、推定出力行は入力とまったく同じです(約1億行)。

クエリは単一のNC列ストアインデックスを使用し、列統計はすべて定期的に更新されます。

8
user107507
  1. これは、CEがどれほど優れていても、クエリがこぼれない可能性がないことを意味しますか?クエリの最大RAMが38 GBにハードキャップされているため

現在のハードウェアとSQL Serverの構成を考えると、クエリの全体的なメモリ許可は37GBに制限されています。

クエリメモリ許可のメモリフラクション(そのプランでは0.860743)内で並べ替えを実行できない場合、tempdbに分類されます。また、この並列ソートは、クエリメモリ許可の一部を12のスレッドに均等に分割し、この割り当ては実行時に再調整できないことに注意してください。

  1. クエリオプティマイザーは、プランを作成するときに最大クエリRAMを考慮しませんか? (ハッシュマッチ集約を強制すると、並べ替え手順が不要になり、クエリのパフォーマンスが大幅に向上します。残念ながら、実際のクエリはCognosからのものであり、制御することはできません。)

はい、ありますが、一般的な原価計算フレームワークへの入力としてのみです。オプティマイザは、そのモデルに応じて、最も安く見える計画を選択します。数値が間違っている場合、プランの選択は最適ではない可能性があります。

あなたの場合、Stream Aggregateによって生成される実際の行数は、見積もりよりも大幅に少なくなります。

Stream Aggregate output

少数の大きなグループが予想される場合、オプティマイザはHash Aggregateを優先します(各グループがハッシュテーブルのスロットを占有するため)。密度に関する誤った情報により、ソート+ストリーム集約の選択が正しくなくなります。

最善の計画は、ネストされたループ結合ではなく、ハッシュ結合とハッシュ集計です。これにより、バッチモード処理を重要な集約ステップに拡張できます。

SQL Server 2012では、行モードとバッチモード間の移行がかなり制限されていました。行モード処理が開始されると、実行エンジンはバッチモードに戻りません(そのため、row-batch-rowは問題ありませんが、batch-row-batchはそうではありません)。

  1. ここで、25%の上限を100%に近づけるのが賢明なオプションでしょうか? (前述のサーバーアクセスを制御して、同時クエリ要求の数を制限できると仮定)

このクエリで使用できるメモリの量を増やしたい場合は、リソースガバナの設定を変更することで確実に増やすことができます。適切な妥協点を見つけることができるかどうかを確認するために、限度を少しずつ増やします。 100%に近づきすぎないように注意します。

クエリがプランガイドに適している場合は、HASH GROUPヒント。

長期的には、SQL Server 2016へのアップグレードは、より多くのオペレーターがバッチモード(並べ替えを含む)で実行でき、動的メモリ許可の増加が可能であり、そして一般的に列ストア/バッチモード処理における他の約1,000の改善により利益をもたらします。

9
Paul White 9

私はあなたの質問に部分的に答えることができます。

1)私はあなたの質問を正確に理解しているのかわかりません。カーディナリティの見積もりが間違っているため、SQLサーバーがtempdbにのみ流出するのは事実ではありません。 SQL Serverは、十分な計画がtempdbに波及することを期待する場合があります。

2)クエリオプティマイザーは、計画を作成するときにサーバー上のメモリを考慮に入れます。有用な演習として、クエリで使用可能なメモリの量を変更して、クエリプランがどのように変化するかを確認します。これは、サーバーのメモリ設定を変更するか、リソースガバナーを使用するか、ドキュメントに記載されていないコマンド DBCC OPTIMIZER WHAT_IF() を使用して行うことができます。 WHAT_IFは、200 GBを超えるメモリでクエリプランがどのように見えるかを確認する場合に役立ちます。

ご指摘のとおり、クエリオプティマイザーはハッシュ一致集計を使用しません。これは、演算子のCPUコストがソートよりもはるかに高くなると考えられるためです。ハッシュ一致の集計をオプティマイザにとって魅力的なものにする基準の1つは、SQL Serverが、返される個別の行が多くないと予測する場合です。クエリに対して、SQL ServerはGROUP BYを含む行を削除しないと考えています。

クエリの利用可能なメモリを変更すると、プランの推定コストはどのくらい近く、どのように変化しますか?

3)わかりませんが、慎重にテストする必要があります。より安全なオプションは、SQL Serverの最大RAMを増やす(200は少し低いように見えますが、サーバーに他のアプリケーションがインストールされているか、これが制御できない)か、tempdbのパフォーマンスを向上させることです。パフォーマンスを改善するための他のいくつかのアイデアを考えることができますが、それらはすべてロングショットです。

ファクトテーブルに対してGROUP BYを実行するだけの簡単なクエリを実行してみてください。個別の値の数をより正確に見積もる方法はありますか?複数列の統計を作成することは役立ちますか?

クエリを変更できない場合は、必要なデータを選択するビューによって参照されるテーブルを置き換えますが、計画は変更されます。これはいくつかのケースで役立ちますが、私はここでテクニックを適用する方法を考えることができません。

このサーバーをかなり制御しているようですので、 計画ガイドの作成 を試すことができます。私はこれをしたことがなく、プランガイドについて誰かが肯定的なことを言うのを聞いたことがありません。

4
Joe Obbish