sql >> データベース >  >> RDS >> Database

同一サーバーのさまざまな計画

    前回の投稿「「同一の」クエリの複数のプラン」では、同じクエリであると思われるものに対して2つの異なるプランを取得する場合と、2つのコピーを取得する場合について説明しました。 同じ 計画します(そしてそれを知らないかもしれません)。そこで調べたように、「同一」はかなり強い言葉になる可能性があります。

    人々をループに陥らせる別のシナリオは、データベースを別のサーバーに復元する場合(たとえば、本番データベースを「同一の」テストサーバーに復元する場合)で、同じクエリに対して異なるパフォーマンス特性または異なるプランを取得します(今回の引用–私は本当に同一のクエリについて話している)

    サーバーは本当に「同一」ですか?

    これらの人似ているように見えるかもしれませんが、まったく同じではありません。

    このシナリオに遭遇した場合、最初に自問する必要があるのは、これら2つのサーバーが本当に同一であるかどうかです。確認すべき点:

    • バージョン –オプティマイザーとクエリの動作の変更の多くは、サービスパックと累積的な更新によってプッシュされます。 「まあ、どちらも2008年だよ!」と言われるのをよく見かけます。 –実際、一方が2008年でもう一方が2008 R2であった場合、またはそれらが異なるサービスパックまたは累積的な更新レベルであった場合。 @@ VERSIONを読んでいる人の多くは、オペレーティングシステムのサービスパック情報をSQL Serverサービスパック情報と間違えているので、次の方が良いと思います。

      SELECT SERVERPROPERTYN'ProductVersion' );

      まったく同じバージョンを使用して、真のリンゴ同士のテストを実行することの重要性を十分に強調することはできません。 SQL Server 2012以降を使用している場合は、ビルドの投稿(SQL Server 2012 | SQL Server 2014)をチェックして、バージョンが一致することを確認するために必要なサービスパックまたは累積的な更新を確認できます。

    • エディション –両方のサーバーで同じエディションを使用していることを願っていますが(ライセンスを除いて、開発者と評価はエンタープライズと同じであるため、同等です)、ここでの不一致は非常に異なる動作につながる可能性があります。たとえば、エディションごとにさまざまな機能の計算能力が異なり、NOEXPANDヒントなしでインデックス付きビューを使用したり、スキーマの変更やインデックスのメンテナンスをオンラインで実行したりする機能など、微妙な機能があります。以下を使用してエディションを比較できます:

      SELECT SERVERPROPERTYN'Edition' );

    • CPUカウント – SQL Serverは、実行プランの作成プロセス中に使用可能なスケジューラーの数を確実に使用します。コアの数が実際のランタイムパフォーマンスに影響を与える可能性があることは否定できません(クロック速度はクエリで重要な要素になることはめったにないため、省略します)。パフォーマンス)。基盤となるサーバーに物理的にインストールされているコアの数を検証するだけでなく、SQLServerのエラーログでSQLServerがライセンスによって実際に使用できるCPUの数を確認します。生のコア数を忘れても、NUMAシステムでは、ここでの人為的な制限により、パフォーマンスプロファイルが大きく異なる可能性があります。詳細については、BrentOzarの最近の投稿「コアベースのライセンスがパフォーマンスチューニングにとって重要である理由」を参照してください。 SQL Server 2012および2014では、設定や物理ハードウェアに関係なく、Standard Editionは16コアしか使用できないため、Editionもここに関連付けられています。 CPUベースのプランの選択とパフォーマンスに異なる影響を与える可能性のあるその他の設定には、リソースガバナー、サーバー全体のMAXDOP、CPUアフィニティ、並列処理のコストしきい値などがあります。
    • メモリの量 – CPUと同様に、オプティマイザーは使用可能なメモリーの量に基づいてプランを選択します。また、CPUと同様に、システムにインストールされているRAMの量だけでなく、SQL Serverに付与されているメモリの量、およびSQLServerが実際に使用している量についても話します。サーバーの最大メモリ設定だけでなく、合計メモリとターゲットメモリ、さらにはDBCCMEMORYSTATUSのパフォーマンスカウンタも確認してください。確認する必要があるその他の事項には、リソースガバナーの設定とメモリ内のページのロックが含まれます。 2つのサーバー間で異なる場合、同じクエリセットで使用されているプラ​​ンキャッシュの量に大きな影響を与える可能性がある設定もあります。アドホックワークロード用に最適化します。 Kimberly Trippには、これに関するすばらしい投稿があります。キャッシュの計画とアドホックワークロードの最適化です。最後に、サーバーが仮想の場合、特にVMメモリ設定が本番環境と一致しない場合や動的である場合は、環境がここで役割を果たす可能性があることに注意してください。
    • バッファプール/プランキャッシュ –テストサーバーでデータベースを復元すると、すぐには準備ができていないことがたくさんあります。バッファプールには、ソースサーバーに存在した可能性のあるデータが含まれていないため、最初にクエリを実行したときにデータをメモリにプライミングするために追加のI/Oが必要になります。また、上記の要因のいくつかが原因でバッファプールが本番環境とは異なる方法で制限されている場合、クエリを複数回実行した後でも同じパフォーマンスパターンを達成できない可能性があります。PaulWhite(@SQL_Kiwi)は、データベース管理者。また、プランキャッシュには本番環境に存在するプランが含まれないため、少なくとも、同じプランが最終的にコンパイルされたとしても(プランが元のプランでコンパイルされたときとは異なるパラメーターが原因で発生しない可能性があります)、サーバー)–追加のコンパイルコストが発生します。また、計画に影響を与えるトレースフラグを設定している場合は、これらが変更される可能性があります。
    • ディスクサブシステム –使用されているディスクの速度とサイズはプランの選択に直接影響しませんが、観察されるパフォーマンスに影響を与える可能性があります。これにより、同じプランで同じクエリが1つで非常に高速に実行される理由がわかります。他よりもシステム。 I /Oは通常SQLServerの最大のボトルネックであり、テストサーバーが実際に同等の製品とまったく同じ基盤となるサブシステムを持っていることは非常にまれです。したがって、2つのシステム間でパフォーマンスの違いが見られ、計画と他のハードウェア要素が同じである場合は、これが次に確認するのに最適な場所である可能性があります。また、SQL Server 2014の時点で、リソースガバナーがI/Oパフォーマンスに制約を課す可能性があることを忘れないでください。
    • トレースフラグ –両方のサーバーに設定されているグローバルトレースフラグのリストを確認します。上記の設定がすべて同じであっても、最適化、計画の動作、および知覚されるパフォーマンスに影響を与える可能性のあるものがいくつかあります。ここに10の一般的で注目すべきものがあります(これは徹底的な回帰テストなしでこれらのいずれかをオンにすることを絶対に推奨するものではありません):

      Flag 説明
      2301 オプティマイザーに、最適な計画を見つけるためにより多くの時間を費やすように強制します。
      2312 SQLServer2014の新しいカーディナリティ推定量を強制します。
      2335 より保守的なメモリ付与を引き起こします。
      2453 テーブル変数を参照するクエリに対してOPTION(RECOMPILE)を強制します。
      2861 SQLServerが些細な/ゼロコストの計画をキャッシュできるようにします。
      4136 事実上、すべてのクエリにOPTIMIZE FOR UNKNOWNを追加します(パラメータのスニッフィングを阻止します)。
      4199 多数のオプティマイザー修正を含む傘。
      8744 ネストされたループのプリフェッチを無効にします。
      9481 SQLServer2014の新しいカーディナリティ推定器をオフにします。


      そのトレースフラグのリストは、決して網羅的なものではありません。私が言うまでもなく求められた文書化されていないものを含めて、他にもたくさんあります。上記にリストされていない他のものを使用している場合(そしてその理由を説明できない場合)、KB#920093、KB#2964518、トレースフラグ(MSDN)、またはSQL Server(TechNet)のトレースフラグに手がかりが見つかる可能性があります。また、Paul Whiteによるさまざまな投稿(ここまたはsql.kiwi)にも貴重な洞察があります。

    • 並行性 –おそらく、テストシステムは、現在テストしているもの以外の目的で使用されます。また、ある種のリプレイを実行していない限り、ワークロードプロファイルも大きく異なる可能性があります。これらのワークロードの違いは、テストしているリクエストを処理するためのリソースの可用性に直接影響を与える可能性があり、ひいてはそれらのリクエストのパフォーマンスに直接影響を与える可能性があります。本番環境には存在しない可能性がある、または存在しているがさまざまな方法で使用されている他のサービス(Analysis Services、Reporting Services、Windowsサービス、さらには独自のアプリケーションなど)を確認することを忘れないでください。逆に、本番環境では、パフォーマンスに影響を与えるこのようなサービスや、テストで模倣されていないインスタンス自体の追加のオーバーヘッドが存在する可能性があります。実際の本番環境のワークロードとは別に、トレース、拡張イベント、影響の大きい監視などについて考えてください。変更の追跡、変更のデータキャプチャ、監査、サービスブローカー、インデックスメンテナンス、バックアップジョブ、DBCCチェック、ミラーリング、レプリケーション、可用性グループ、そしてリストはどんどん増えていきます…

    データベースはまだ「同一」ですか?

    すべてのハードウェア変数とワークロード変数が十分に一致していると仮定すると、データベースを同じままにすることは依然として困難な場合があります。テストシステムへのバックアップ/復元を実行している場合、新しいデータベースはソースと同じものとして開始されます(物理的な場所とセキュリティを除く)。ただし、何らかの方法でタッチを開始するとすぐに、次のいずれかまたはすべてを実行できるため、本番コピーからすぐに逸脱します。

    • データ、スキーマ、またはその両方を変更します。
    • 誤って統計の自動更新を開始しました。
    • インデックスを手動で追加、最適化、再構築するか、統計を作成または更新します。
    • 互換性レベル、分離レベル、強制パラメーター化、選択的XMLインデックス、または「自動」-という名前のオプションなどのデータベース設定を変更します。 (データとログファイルの場所と拡張設定でさえ、クエリのパフォーマンスに影響を与える可能性があります。これにはtempdbも含まれます。)
    • プランキャッシュ、バッファプール、またはその両方を直接、または他のイベント(RECONFIGUREやサービスの再起動など)の副作用として空にします。

    また、新しいクエリプランの生成を開始すると、上記の変更が行われる前であっても、本番環境で同じクエリのプランを生成するために使用されるデータとは異なるデータに基づいている可能性があることに注意する必要があります。例として、計画が本番環境でコンパイルされたときのカーディナリティは、その時点とバックアップの時間の間で大幅に偏っていた可能性があります。つまり、新しい計画はさまざまな統計とヒストグラム情報に基づいて生成されます。

    これが実際には最近の復元ではなく、他の方法(スキーマやデータの変更の手動展開、さらにはレプリケーションなど)で同期を維持している2つのスキーマとデータセットである場合、これらはさらに分岐します。ディスク容量の制限により、本番データのサブセットのみ、または統計のみのクローンを取得した場合もあります。これらのデータの違いにより、最も単純なクエリを除くすべてのクエリで、パフォーマンス特性が異なる可能性があります。運が良ければ、同じプランをいくつか手に入れることができます。

    クエリは本当に「同一」ですか?

    上記のすべてがチェックアウトされたとしても、セッション設定(SSMSの異なるコピー、異なる設定、または異なるクライアントツールを使用している可能性があります)、または異なるデフォルトスキーマ(異なるデフォルトスキーマ)のために異なるプランを取得しているシナリオがまだあります。たとえば、別のWindowsまたはSQL認証ログインとしてテストサーバーに接続している可能性があります)。以前の投稿でこれらのことについてたくさん話しました。

    結論

    いくつかの違いを軽減する方法はありますが(テストサーバーをだまして、基盤となるハードウェアに関する驚異的なことを信じさせるためのDBCC OPTIMIZER_WHATIFを確認してください)、2つのサーバーのパフォーマンスを確実かつ一貫して同一にすることは非常に困難です。 2つの類似した(または同一の)サーバーで異なるプランまたは異なるパフォーマンスが得られる理由は、潜在的に数十あります。

    何か特別なトリックはありますか?上記のアイデア(または私が言及しなかった他のアイデア)に耐え難い問題点はありますか?以下のコメントで共有してください!


    1. SQLServerクエリのUNIONALLとOR条件

    2. グループごとに最初と最後の行から値を取得します

    3. テーブル列の結果からSQLカスタムテキストを表示する

    4. select SCOPE_IDENTITY()が整数ではなく小数を返すのはなぜですか?