더 많은 CPU 및 RAM 할당 후 SQL Server 성능 저하


33

가상 Windows 2008 R2 서버에서 SQL Server 2008 R2 (10.50.1600)를 실행하고 있습니다. CPU를 1 코어에서 4로 업그레이드하고 RAM을 4GB에서 10GB로 업그레이드 한 후 성능이 저하되는 것을 알았습니다.

내가 본 몇 가지 관찰 :

  1. 실행하는 데 5 초 미만의 쿼리가 이제 200 초 이상 걸립니다.
  2. CPU는 sqlservr.exe를 범인으로하여 100에 페깅됩니다.
  3. 460 만 개의 행이있는 테이블에서 select count (*)가 90 초 이상 걸렸습니다.
  4. 서버에서 실행중인 프로세스는 변경되지 않았습니다. 유일한 변화는 CPU와 램을 늘리는 것이 었습니다.
  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 년 전에 나왔던 최신 서비스 팩을 우선적으로 받고 싶을 것입니다. 그렇게하면 이상한 버그 나 무언가를 치는 경우 보상받을 수 있습니다. 머리에 이상 여기가 당신이 다운로드 할 필요가 무엇인지 알아낼 수 있습니다.

  2. vCPU를 추가하고 (1 ~ 4) 설정을 변경하지 않았으므로 이제 쿼리가 병렬로 진행될 수 있습니다. 나는 이것이 모두 더 빠를 것 같지만 잠깐만 요!

  3. RAM을 추가했을 수 있지만 서버가 활용할 수 있도록 Max Server Memory를 변경하지 않았을 수 있습니다.

  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 리포지토리에 있음) 와 같은 것을 사용 하여 쿼리 계획 캡처를 시작해야합니다. 대기 통계 외에도, 무엇이 잘못되었는지 파악하기 위해 볼 수있는 가장 중요한 것 중 하나입니다.

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

내가 지적하지 않은 한 가지는 VM에 vCPU를 추가하면 예약으로 인해 속도가 느려질 수 있다는 것입니다.

기본 개념은 VM에 4 개의 vCPU가있는 경우 하이퍼 바이저는 4 개의 물리적 코어가 사용 가능할 때까지 기다려야하므로 3 개가 유휴 상태 인 경우에도 모든 vCPU를 예약 할 수 있습니다.

호스트에 코어가 많지 않고 다른 워크로드가 사용중인 경우 추가 대기가 발생하고 성능이 크게 저하 될 수 있습니다.

VMware ESXi에서는 CPU Ready를 통해 고급 그래프에서 볼 수 있습니다.

다음은 이러한 상황에 대한 실제 사례와 진단 방법이 나와있는 많은 기사 중 하나입니다 .

VM의 RAM 할당이 NUMA 노드보다 큰 경우 RAM을 더 추가하면 성능이 갑자기 저하 될 수 있습니다.

또한 vCPU 구성 (vSocket과 vCore)은 실제로 SQL Server와 같은 일부 응용 프로그램에 영향을 줄 수 있습니다. 이는 SQL 서버 자체가 NUMA를 인식하고 (같은 종류의 NUMA 스패닝 성능 저하를 피하기 위해) VMware가 가상 NUMA 노드를 다르게 표시 할 수 있기 때문입니다.

이 내용은 VMware 자체 사이트의 블로그 게시물에서 다룹니다 .


에릭의 도움으로 문제를 해결하게되어 기쁘지만, 이것들을보고 고려할 수도 있습니다.


3

@sp_BlitzErik의 답변을 계속하는 약간의 도움 (이 글을 코멘트로 게시 할 수 없음), Pinal 및 Max Vernon (어디에서 기억할 수 없음)에 대해 MAXDOP을 얼마나 사용해야하는지에 대한 쿼리가 있습니다.

/*************************************************************************
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));

첫 번째 스크립트는 빈 결과를 반환합니다. 두 번째는 MAXDOP = 2@sp_BlitzErik과 일치 하는 제안 을 반환합니다 . 감사!
Jeff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.