UATサーバーとPRODサーバーの実行計画の違い


39

UAT(3秒で実行)とPROD(23秒で実行)で同じクエリを実行すると、なぜこんなに大きな違いがあるのか​​を理解したいと思います。

UATとPRODの両方に、正確なデータとインデックスがあります。

クエリ:

set statistics io on;
set statistics time on;

SELECT CONF_NO,
       'DE',
       'Duplicate Email Address ''' + RTRIM(EMAIL_ADDRESS) + ''' in Maintenance',
       CONF_TARGET_NO
FROM   CONF_TARGET ct
WHERE  CONF_NO = 161
       AND LEFT(INTERNET_USER_ID, 6) != 'ICONF-'
       AND ( ( REGISTRATION_TYPE = 'I'
               AND (SELECT COUNT(1)
                    FROM   PORTFOLIO
                    WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                           AND DEACTIVATED_YN = 'N') > 1 )
              OR ( REGISTRATION_TYPE = 'K'
                   AND (SELECT COUNT(1)
                        FROM   CAPITAL_MARKET
                        WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                               AND DEACTIVATED_YN = 'N') > 1 ) ) 

UATで:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 11 ms, elapsed time = 11 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'Worktable'. Scan count 256, logical reads 1304616, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PORTFOLIO'. Scan count 1, logical reads 84761, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 2418 ms,  elapsed time = 2442 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

ここに画像の説明を入力してください

PRODについて:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'PORTFOLIO'. Scan count 256, logical reads 21698816, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 23937 ms,  elapsed time = 23935 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

ここに画像の説明を入力してください

PRODではクエリがインデックスの欠落を示唆しており、これはテストしたとおり有益ですが、それは議論のポイントではないことに注意してください。

私はそれを理解したいだけです:UATで-なぜSQLサーバーはワーカーテーブルを作成し、PRODでは作成しませんか?PRODではなくUATでテーブルスプールを作成します。また、なぜUATとPRODで実行時間がそんなに異なるのですか?

注意 :

私は両方のサーバーでSQL Server 2008 R2 RTMを実行しています(すぐに最新のSPを適用する予定です)。

UAT:最大メモリ8GB。MaxDop、プロセッサアフィニティ、および最大ワーカースレッドは0です。

Logical to Physical Processor Map:
*-------  Physical Processor 0
-*------  Physical Processor 1
--*-----  Physical Processor 2
---*----  Physical Processor 3
----*---  Physical Processor 4
-----*--  Physical Processor 5
------*-  Physical Processor 6
-------*  Physical Processor 7

Logical Processor to Socket Map:
****----  Socket 0
----****  Socket 1

Logical Processor to NUMA Node Map:
********  NUMA Node 0

PROD:最大メモリ60GB。MaxDop、プロセッサアフィニティ、および最大ワーカースレッドは0です。

Logical to Physical Processor Map:
**--------------  Physical Processor 0 (Hyperthreaded)
--**------------  Physical Processor 1 (Hyperthreaded)
----**----------  Physical Processor 2 (Hyperthreaded)
------**--------  Physical Processor 3 (Hyperthreaded)
--------**------  Physical Processor 4 (Hyperthreaded)
----------**----  Physical Processor 5 (Hyperthreaded)
------------**--  Physical Processor 6 (Hyperthreaded)
--------------**  Physical Processor 7 (Hyperthreaded)

Logical Processor to Socket Map:
********--------  Socket 0
--------********  Socket 1

Logical Processor to NUMA Node Map:
********--------  NUMA Node 0
--------********  NUMA Node 1

更新:

UAT実行計画XML:

http://pastebin.com/z0PWvw8m

PROD実行計画XML:

http://pastebin.com/GWTY16YY

UAT実行計画XML-PRODから生成された計画:

http://pastebin.com/74u3Ntr0

サーバー構成:

PROD:PowerEdge R720xd-Intel(R)Xeon(R)CPU E5-2637 v2 @ 3.50GHz。

UAT:PowerEdge 2950-Intel(R)Xeon(R)CPU X5460 @ 3.16GHz

私はanswers.sqlperformance.comに投稿しました


更新:

提案してくれた@swasheckに感謝

PRODの最大メモリを60GBから7680 MBに変更すると、PRODで同じプランを生成できます。クエリはUATと同じ時間で完了します。

今、私は理解する必要があります-なぜですか?また、これによって、このモンスターサーバーを古いサーバーに置き換えることを正当化することはできません!

回答:


43

バッファプールの潜在的なサイズは、クエリオプティマイザーによるプランの選択にいくつかの方法で影響します。私の知る限り、ハイパースレッディングはプランの選択に影響しません(ただし、潜在的に使用可能なスケジューラの数は確かに影響します)。

ワークスペースメモリ

並べ替えやハッシュなどのメモリ消費イテレータを含むプランの場合、バッファプールのサイズは(とりわけ)実行時にクエリで使用できるメモリ許可の最大量を決定します。

SQL Server 2012(すべてのバージョン)では、この番号は、クエリプランのルートノードで、Optimizer Hardware Dependenciesセクションとして報告されますEstimated Available Memory Grant。2012年より前のバージョンは、ショープランでこの数を報告しません。

推定使用可能メモリ許可は、クエリオプティマイザーが使用するコストモデルへの入力です。その結果、大規模なソートまたはハッシュ操作を必要とする代替プランは、設定が低いマシンよりもバッファープールが大きいマシンで選択される可能性が高くなります。非常に大量のメモリを搭載したインストールの場合、このような考え方ではコストモデルが行き過ぎます。代替戦略が望ましい非常に大きなソートまたはハッシュのプランを選択してください(KB2413549-大量のメモリを使用すると、 SQL Serverの非効率的な計画-TF2335)。

ワークスペースのメモリ許可はあなたの場合の要因ではありませんが、知っておく価値のあるものです。

データアクセス

バッファプールの潜在的なサイズは、データアクセスのオプティマイザのコストモデルにも影響します。モデルで行われた仮定の1つは、すべてのクエリがコールドキャッシュで始まるということです。したがって、ページへの最初のアクセスでは物理I / Oが発生すると想定されます。このモデルは、繰り返しアクセスがキャッシュから発生する可能性を考慮しようとしますが、この要因は、とりわけバッファープールの潜在的なサイズに依存します。

質問に示されているクエリプランのクラスター化インデックススキャンは、繰り返しアクセスの1つの例です。ネストされたループの準結合の反復ごとに、スキャンが巻き戻されます(相関パラメーターの変更なしで繰り返されます)。半結合への外部入力は28.7874行を推定し、これらのスキャンのクエリプランプロパティは結果として27.7874での推定巻き戻しを示しています。

繰り返しますが、SQL Server 2012のみで、プランのルートイテレーターはセクションEstimated Pages Cached内のの数を示しますOptimizer Hardware Dependencies。この数値は、キャッシュからの繰り返しページアクセスの可能性を考慮したコスト計算アルゴリズムへの入力の1つを報告します。

その結果、最大バッファプールサイズを大きく設定したインストールは、最大バッファプールサイズを小さくしたインストールよりも同じページを複数回読み取るスキャン(またはシーク)のコストを削減する傾向があります。

単純な計画では、巻き戻されたスキャンのコスト削減は、(estimated number of executions) * (estimated CPU + estimated I/O)より低い推定オペレーターコストと比較することで確認できます。例の計画では、準結合と結合の効果により計算がより複雑になります。

それでも、質問の計画は、スキャンを繰り返すか、一時インデックスを作成するかの選択が非常にバランスが取れている場合を示しているように見えます。バッファプールが大きいマシンでは、スキャンの繰り返しのコストは、インデックスの作成よりもわずかに低くなります。バッファプールが小さいマシンでは、スキャンコストが少なくなります。つまり、オプティマイザーにとってインデックススプールプランが少し安く見えるということです。

プランの選択

オプティマイザーのコストモデルには、多くの仮定があり、多数の詳細な計算が含まれています。必要なすべての数値が公開されているわけではなく、リリースごとにアルゴリズムが変更される可能性があるため、すべての詳細に従うことが常に(または通常)可能とは限りません。特に、キャッシュされたページに遭遇する可能性を考慮するために適用されるスケーリング式はよく知られていません。

この特定の場合のポイントまで、オプティマイザーのプランの選択はいずれにしても間違った数値に基づいています。クラスター化インデックスシークからの推定行数は28.7874ですが、実行時に256行が検出されます-ほぼ1桁のアウトです。これらの28.7874行内の値の予想される分布に関してオプティマイザーが持っている情報を直接見ることはできませんが、恐ろしく間違っている可能性が非常に高いです。

見積もりがこのように間違っている場合、プランの選択と実行時のパフォーマンスは、本質的に偶然よりも優れています。インデックススプールとの計画が起こるスキャンを繰り返すよりも良好に機能するが、バッファプールのサイズを大きくすると、異常の原因だったことを考えるのは非常に間違っています。

オプティマイザーが正しい情報を持っている場合、適切な実行計画を作成する可能性がはるかに高くなります。一般に、メモリが多いインスタンスは、メモリが少ない別のインスタンスよりもワークロードでパフォーマンスが向上しますが、特にプランの選択が誤ったデータに基づいている場合は保証されません。

両方のインスタンスは、独自の方法でインデックスの欠落を示唆しました。1つは明示的なインデックスの欠落を報告し、もう1つは同じ特性のインデックススプールを使用しました。インデックスが優れたパフォーマンスとプランの安定性を提供する場合、それで十分かもしれません。私も、クエリを書き直したいと思っていますが、それはおそらく別の話です。


18

Paul Whiteは優れた明快な方法でその背後にある理由を説明しました-より多くのメモリを備えたサーバーで実行するときのSQLサーバーの動作。

また、問題を最初に発見してくれた@swasheckに大いに感謝します。

マイクロソフトとのケースを開き、以下が提案されたものです。

この問題は、トレースフラグT2335をスタートアップパラメーターとして使用することで解決されます。

KB2413549 -大量のメモリを使用すると、SQL Serverで非効率的な計画につながることができますが、より詳細にそれを説明しています。

このトレースフラグにより​​、SQL Serverは、クエリの実行時にメモリ消費の観点からより保守的なプランを生成します。SQL Serverが使用できるメモリ量は制限されません。SQL Server用に構成されたメモリは、引き続きデータキャッシュ、クエリ実行、およびその他のコンシューマーによって使用されます。このオプションを実稼働環境に展開する前に、このオプションを徹底的にテストしてください。


13

最大メモリ設定とハイパースレッディングはどちらもプランの選択に影響を与える可能性があります。

また、環境ごとに「設定」オプションが異なることに気付きました。

UATのStatementSetOptions:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="true" 
CONCAT_NULL_YIELDS_NULL="true" 
NUMERIC_ROUNDABORT="false" 
QUOTED_IDENTIFIER="true" 

製品のStatementSetOptions:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="false" 
CONCAT_NULL_YIELDS_NULL="true"
NUMERIC_ROUNDABORT="false"
QUOTED_IDENTIFIER="true" 

SQLは、SETオプションに基づいて異なるプランを生成できます。これは、異なるSSMSセッションから、またはアプリからの異なる実行から計画をキャプチャしている場合に頻繁に発生します。

開発者が一貫した接続文字列を使用していることを確認してください。


2
Max MemoryとHyperthreadingがプランキャッシュに影響を与える可能性があると述べているのは正しいですが、これが何で、なぜ起こったのかについて詳しく知りたいです。答えに感謝します。
キンシャー

2
アマンダが言ったように、SETオプションがARITHABORTで異なる場合は、dba.stackexchange.com / questions / 9840 /を見る必要があるかもしれません
ARA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.