より多くのCPUとRAMを割り当てた後のSQL Serverパフォーマンスの低下


33

仮想Windows 2008 R2サーバーで実行されているSQL Server 2008 R2(10.50.1600)があります。CPUを1コアから4に、RAMを4 GBから10 GBにアップグレードした後、パフォーマンスが低下していることに気付きました。

私が見るいくつかの観察:

  1. 実行に5秒未満かかったクエリは、現在200秒以上かかっています。
  2. CPUは、sqlservr.exeを原因として100に固定されています。
  3. 4.6百万行のテーブルでのselect count(*)は90秒以上かかりました。
  4. サーバーで実行されているプロセスは変更されていません。唯一の変更点は、CPUとRAMを増やすことでした。
  5. 他のSQLサーバーには静的なページングファイルがあり、このサーバーはそれを独自に管理するように設定されています。

以前にこの問題に遭遇した人はいますか?

sp_BlitzErikごとに、私は走りました

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

これらの結果を与えてくれます。

統計を待つ


9
前回SEで同様の質問を見たのは、誰かがVMのCPUとRAMを起動したが、VMホストには実際にはそれほど多くのCPUと RAM がなかったためです。最初に確認します。
user253751

回答:


55

ここでは多くのことが行われていますが、そのほとんどはかなり広範で曖昧です。

  1. 2008R2 RTMは2010年4月21日にリリースされました。完全にサポート対象外です。ちょうど3年前にリリースされた最新のService Packを優先的に使用する必要があります。そうすれば、奇妙なバグや何かにぶつかった場合にカバーされます。上の頭の上に、ここであなたがダウンロードする必要があるかを把握します。

  2. vCPU(1〜4)を追加し、設定を変更しなかったため、クエリを並行して実行できます。これはすべて速くなるように聞こえますが、しばらくお待ちください!

  3. RAMを追加したかもしれませんが、サーバーがそれを利用できるように、最大​​サーバーメモリを変更していない可能性があります。

  4. サーバーが待機しているものを把握します。私が取り組んでいるオープンソースプロジェクトでは、SQL Serverの測定に役立つ無料のスクリプトを提供しています。上の頭の上にここにあなたがそれらを試してみるしたい場合。

サーバーの待機状態を確認するには、sp_BlitzFirstを取得します。いくつかの方法で実行できます。

これにより、サーバーが起動してから何を待っているかがわかります。

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

これにより、30秒のウィンドウの間に現在待機しているクエリが表示されます。

EXEC dbo.sp_BlitzFirst @Seconds = 30, @ExpertMode = 1;

どのクエリが待機しているかを把握したら(待機統計について書かれたものが山ほどあります)、物事を制御するために変更を開始できます。

それらが待機しているのを見ればCXPACKET、それはあなたのクエリが並行しており、おそらく互いに踏みつけていることを意味します。これに達した場合、おそらく並列処理のコストしきい値を最大50に上げ、おそらくMAXDOPを2に下げることを検討する必要があります。

この手順の後、sp_WhoIsActiveやsp_BlitzWho(後者は以前のGitHubリポジトリにあります)などを使用してクエリプランのキャプチャを開始します。待機統計は別として、それらは何が悪いのかを理解するために見ることができる最も重要なものの1つです。

また、SQL Serverに関連してチェックアウトするVMWareカウンターに関するJonathan Kehayiasによるこの記事をチェックアウトすることもできます。

更新

待機統計と少年を確認すると、彼らは奇妙です。CPUには間違いなく何かがあります。サーバーはほとんど退屈していますが、状況が悪化すると事態は悪化します。これを簡単に分解してみます。

  1. と呼ばれる毒待ちを打っていますTHREADPOOL。あなたはそれのトンを持っていませんが、あなたのサーバーがひどくアクティブではないので、それは理にかなっています。その理由をすぐに説明します。

  2. あなたは本当に長い平均待ち時間がSOS_SCHEDULER_YIELDありCXPACKETます。VMを使用しているので、SQL Serverに予約があるか、ボックスがひどくオーバーサブスクライブされていないことを確認します。騒々しい隣人はここであなたの一日を本当に台無しにすることができます。また、サーバー/ VMゲスト/ VMホストがバランス電源モードで実行されていないことを確認する必要があります。これにより、CPUが不必要に低速にスピンダウンし、すぐに最高速度に戻りません。

  3. 彼らはどのように結びついていますか?4つのCPUを使用すると、512のワーカースレッドがあります。単一のCPU でも同じ量でしたが、クエリを並列処理できるようになったため、より多くのワーカースレッドを消費できることに注意してください。あなたの場合、並列クエリの並列分岐ごとに4つのスレッド。

平行して何が起こっていますか?おそらくすべて。並列処理のデフォルトのコストしきい値は5です。この数値は、90年代後半に、このように見えるデスクトップでの作業中にデフォルトになりました。

ナッツ

確かに、ハードウェアはほとんどのラップトップよりも小さいですが、それでもまだ少し先を行っています。

多数の並列クエリが実行されると、これらのワーカースレッドが不足します。その場合、クエリはスレッドが実行されるのを待つだけです。SOS_SCHEDULER_YIELDクエリがCPUからステップオフし、長い間戻らないこともあります。ブロッキング待機は表示されないので、ほとんどの場合、クエリ内並列処理の待機がすべて詰まっています。

何ができる?

  1. バランスのとれた電力モードになっていないことを確認
  2. MAXDOPを2に変更
  3. 並列処理のコストしきい値を50に変更します
  4. 上記のJon K.の記事に従って、VMの正常性を検証してください。
  5. 呼び出さsp_BlitzIndexれたスクリプトを使用して、欠落しているインデックス要求を探します。

より徹底的なトラブルシューティングについては、クラウドでのハードウェアサイジングに関するGoogle向けホワイトペーパーをご覧ください。

お役に立てれば!



5

私が指摘していなかった1つのことは、VMにvCPUを追加すると、スケジューリングのために非常に頻繁に遅くなる可能性があるということです。

基本的な考え方は、VMに4つのvCPUがある場合、ハイパーバイザーは4つの物理コアが使用可能になるのを待たなければならないため、3つのvCPUがアイドル状態であってもすべてのvCPUをスケジュールできます。

ホストに多くのコアがなく、他のワークロードがビジーである場合、余分な待機が発生し、パフォーマンスが大幅に低下する可能性があります。

VMware ESXiでは、CPU Readyを介して高度なグラフで確認できます。

この出来事とそれがどのように診断されたかの実世界の例を含む多くの記事の1つです

VMのRAM割り当てがNUMAノードよりも大きい場合、RAMを追加すると突然パフォーマンスが低下する可能性があります。

さらに、vCPUの構成(vSockets対vCores)は、実際にはSQLサーバーなどの一部のアプリケーションに影響を与える可能性があります。これは、SQLサーバー自体が(同じ種類のNUMAスパンパフォーマンス低下を避けるために)NUMAを認識し、VMwareが仮想NUMAノードを異なる方法で提示する可能性があるためです。

これはVMware自身のサイトのブログ投稿で説明されています


そうは言っても、エリックの助けを借りて問題を解決できてうれしいですが、これらのことも見て検討したいと思うかもしれません。


3

@sp_BlitzErikの答えを続けるために少し助けてください(これをコメントとして投稿することはできません)。

/*************************************************************************
Author          :   Kin Shah
Purpose         :   Recommend MaxDop settings for the server instance
Tested RDBMS    :   SQL Server 2008R2

**************************************************************************/
declare @hyperthreadingRatio bit
declare @logicalCPUs int
declare @HTEnabled int
declare @physicalCPU int
declare @SOCKET int
declare @logicalCPUPerNuma int
declare @NoOfNUMA int

select @logicalCPUs = cpu_count -- [Logical CPU Count]
    ,@hyperthreadingRatio = hyperthread_ratio --  [Hyperthread Ratio]
    ,@physicalCPU = cpu_count / hyperthread_ratio -- [Physical CPU Count]
    ,@HTEnabled = case 
        when cpu_count > hyperthread_ratio
            then 1
        else 0
        end -- HTEnabled
from sys.dm_os_sys_info
option (recompile);

select @logicalCPUPerNuma = COUNT(parent_node_id) -- [NumberOfLogicalProcessorsPerNuma]
from sys.dm_os_schedulers
where [status] = 'VISIBLE ONLINE'
    and parent_node_id < 64
group by parent_node_id
option (recompile);

select @NoOfNUMA = count(distinct parent_node_id)
from sys.dm_os_schedulers -- find NO OF NUMA Nodes 
where [status] = 'VISIBLE ONLINE'
    and parent_node_id < 64

-- Report the recommendations ....
select
    --- 8 or less processors and NO HT enabled
    case 
        when @logicalCPUs < 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : ' + CAST(@logicalCPUs as varchar(3))
                --- 8 or more processors and NO HT enabled
        when @logicalCPUs >= 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : 8'
                --- 8 or more processors and HT enabled and NO NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA = 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
                --- 8 or more processors and HT enabled and NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA > 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
        else ''
        end as Recommendations

-------------------------------------------------- -------

--MAX VERNON 

/* 
   This will recommend a MAXDOP setting appropriate for your machine's NUMA memory
   configuration.  You will need to evaluate this setting in a non-production 
   environment before moving it to production.

   MAXDOP can be configured using:  
   EXEC sp_configure 'max degree of parallelism',X;
   RECONFIGURE

   If this instance is hosting a Sharepoint database, you MUST specify MAXDOP=1 
   (URL wrapped for readability)
   http://blogs.msdn.com/b/rcormier/archive/2012/10/25/
   you-shall-configure-your-maxdop-when-using-sharepoint-2013.aspx

   Biztalk (all versions, including 2010): 
   MAXDOP = 1 is only required on the BizTalk Message Box
   database server(s), and must not be changed; all other servers hosting other 
   BizTalk Server databases may return this value to 0 if set.
   http://support.microsoft.com/kb/899000
*/
SET NOCOUNT ON;

DECLARE @CoreCount int;
SET @CoreCount = 0;
DECLARE @NumaNodes int;

/*  see if xp_cmdshell is enabled, so we can try to use 
    PowerShell to determine the real core count
*/
DECLARE @T TABLE (
    name varchar(255)
    , minimum int
    , maximum int
    , config_value int
    , run_value int
);
INSERT INTO @T 
EXEC sp_configure 'xp_cmdshell';
DECLARE @cmdshellEnabled BIT;
SET @cmdshellEnabled = 0;
SELECT @cmdshellEnabled = 1 
FROM @T
WHERE run_value = 1;
IF @cmdshellEnabled = 1
BEGIN
    CREATE TABLE #cmdshell
    (
        txt VARCHAR(255)
    );
    INSERT INTO #cmdshell (txt)
    EXEC xp_cmdshell 'powershell -OutputFormat Text -NoLogo -Command "& {Get-WmiObject -namespace "root\CIMV2" -class Win32_Processor -Property NumberOfCores} | select NumberOfCores"';
    SELECT @CoreCount = CONVERT(INT, LTRIM(RTRIM(txt)))
    FROM #cmdshell
    WHERE ISNUMERIC(LTRIM(RTRIM(txt)))=1;
    DROP TABLE #cmdshell;
END
IF @CoreCount = 0 
BEGIN
    /* 
        Could not use PowerShell to get the corecount, use SQL Server's 
        unreliable number.  For machines with hyperthreading enabled
        this number is (typically) twice the physical core count.
    */
    SET @CoreCount = (SELECT i.cpu_count from sys.dm_os_sys_info i); 
END

SET @NumaNodes = (
    SELECT MAX(c.memory_node_id) + 1 
    FROM sys.dm_os_memory_clerks c 
    WHERE memory_node_id < 64
    );

DECLARE @MaxDOP int;

/* 3/4 of Total Cores in Machine */
SET @MaxDOP = @CoreCount * 0.75; 

/* if @MaxDOP is greater than the per NUMA node
    Core Count, set @MaxDOP = per NUMA node core count
*/
IF @MaxDOP > (@CoreCount / @NumaNodes) 
    SET @MaxDOP = (@CoreCount / @NumaNodes) * 0.75;

/*
    Reduce @MaxDOP to an even number 
*/
SET @MaxDOP = @MaxDOP - (@MaxDOP % 2);

/* Cap MAXDOP at 8, according to Microsoft */
IF @MaxDOP > 8 SET @MaxDOP = 8;

PRINT 'Suggested MAXDOP = ' + CAST(@MaxDOP as varchar(max));

最初のスクリプトは空の結果を返します。2番目はMAXDOP = 2@sp_BlitzErikに沿った正しい提案を返します。ありがとう!
ジェフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.