Verlangsamte SQL Server-Leistung nach Zuweisung von mehr CPU und RAM


33

Wir haben SQL Server 2008 R2 (10.50.1600) auf einem virtuellen Windows 2008 R2-Server ausgeführt. Nach dem Upgrade der CPU von 1 auf 4 und des Arbeitsspeichers von 4 auf 10 GB haben wir festgestellt, dass die Leistung schlechter ist.

Einige Beobachtungen, die ich sehe:

  1. Eine Abfrage, deren Ausführung <5 Sekunden dauerte, dauert jetzt> 200 Sekunden.
  2. Die CPU ist mit sqlservr.exe als Schuldigen auf 100 festgelegt.
  3. Eine ausgewählte Anzahl (*) in einer Tabelle mit 4,6 Millionen Zeilen dauerte über 90 Sekunden.
  4. Die Prozesse, die auf dem Server ausgeführt werden, haben sich nicht geändert. Die einzige Änderung bestand darin, die CPU und den RAM zu erhöhen.
  5. Andere SQL-Server verfügen über eine statische Auslagerungsdatei, in der dieser Server so eingestellt ist, dass er sie selbst verwaltet.

Ist schon jemand auf dieses Problem gestoßen?

Per sp_BlitzErik bin ich gelaufen

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

Gib mir diese Ergebnisse.

warte Statistiken


9
Als ich das letzte Mal eine ähnliche Frage zu SE sah, war dies darauf zurückzuführen, dass jemand die VM-CPUs und den RAM aufgedreht hatte , der VM-Host jedoch nicht über so viele CPUs und so viel RAM verfügte . Also würde ich das zuerst überprüfen.
user253751

Antworten:


55

Hier ist viel los, und das meiste ist ziemlich breit und vage.

  1. 2008R2 RTM wurde am 21. April 2010 veröffentlicht. Sie sollten vorrangig auf das neueste Service Pack zugreifen, das vor etwa drei Jahren auf den Markt kam. Auf diese Weise werden Sie abgedeckt, wenn Sie einen seltsamen Fehler oder etwas treffen. Gehen Sie hierher, um herauszufinden, was Sie herunterladen müssen.

  2. Da Sie vCPUs (von 1 bis 4) hinzugefügt und keine Einstellungen geändert haben, können Ihre Abfragen jetzt parallel ausgeführt werden. Ich weiß, das hört sich so an, als wären sie alle schneller, aber warte!

  3. Möglicherweise haben Sie RAM hinzugefügt, aber möglicherweise nicht den maximalen Serverspeicher geändert, damit Ihr Server davon Gebrauch machen kann.

  4. Finden Sie heraus, worauf Ihr Server wartet. Ein Open-Source-Projekt, an dem ich arbeite, stellt kostenlose Skripte zur Verfügung, mit denen Sie Ihren SQL Server messen können. Kommen Sie hierher, wenn Sie es versuchen wollen.

Greifen Sie zu sp_BlitzFirst, um die Wartestatistiken Ihres Servers zu überprüfen. Sie können es auf verschiedene Arten ausführen.

Dies zeigt Ihnen, worauf Ihr Server seit dem Start gewartet hat.

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

Dies zeigt Ihnen in einem 30-Sekunden-Fenster, worauf Abfragen jetzt warten.

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

Sobald Sie herausgefunden haben, worauf Abfragen warten (es gibt eine Menge Informationen zu Wartestatistiken), können Sie Änderungen vornehmen, um die Dinge unter Kontrolle zu bringen.

Wenn Sie sehen CXPACKET, dass sie warten , bedeutet dies, dass Ihre Abfragen parallel verlaufen und sich möglicherweise überschlagen. Wenn Sie diese Option auswählen, sollten Sie den Kostengrenzwert für Parallelität möglicherweise auf 50 erhöhen und MAXDOP möglicherweise auf 2 senken.

Nach diesem Schritt können Sie beispielsweise sp_WhoIsActive oder sp_BlitzWho (letzteres ist im GitHub-Repo von früher enthalten) zum Erfassen von Abfrageplänen verwenden. Abgesehen von Wartestatistiken sind sie eines der wichtigsten Dinge, die Sie sich ansehen können, um herauszufinden, was falsch läuft.

Vielleicht möchten Sie auch diesen Artikel von Jonathan Kehayias über VMWare-Zähler lesen , um ihn in Bezug auf SQL Server zu lesen .

Aktualisieren

Das Überprüfen der Wartestatistiken und des Jungen sind sie sonderbar. Bei den CPUs ist definitiv etwas los. Ihr Server sitzt meistens gelangweilt herum, aber wenn es heiß hergeht, wird es schlimm. Ich werde versuchen, dies leicht zu brechen.

  1. Sie treffen eine Giftwartezeit genannt THREADPOOL. Sie haben nicht viel davon, aber das macht Sinn, weil Ihr Server nicht besonders aktiv ist. Ich erkläre gleich warum.

  2. Sie haben wirklich lange durchschnittliche Wartezeiten auf SOS_SCHEDULER_YIELDund CXPACKET. Sie befinden sich auf einer VM und möchten sicherstellen, dass der SQL Server Reservierungen hat oder dass die Box nicht schrecklich überzeichnet ist. Ein lauter Nachbar kann Ihren Tag hier wirklich ruinieren. Sie sollten auch sicherstellen, dass der Server / VM-Gast / VM-Host nicht im ausgeglichenen Stromversorgungsmodus ausgeführt wird. Dadurch werden Ihre CPUs auf unnötig niedrige Geschwindigkeiten heruntergefahren und nicht sofort wieder auf die volle Geschwindigkeit hochgefahren.

  3. Wie binden sie ein? Mit 4 CPUs haben Sie 512 Worker-Threads. Denken Sie daran, Sie hatten dieselbe Menge mit einer einzelnen CPU, aber jetzt, da Ihre Abfragen parallel ausgeführt werden können, können sie viel mehr Arbeitsthreads verbrauchen. In Ihrem Fall 4 Threads pro parallelem Zweig einer parallelen Abfrage.

Was läuft parallel? Höchstwahrscheinlich alles. Die Standardkostenschwelle für Parallelism ist 5. Diese Zahl die Standardirgendwann in den späten 90er Jahren gemacht wurde auf einem Desktop arbeiten , dass sah wie folgt aus .

NÜSSE

Zugegeben, Ihre Hardware ist kleiner als die der meisten Laptops, aber Sie sind der Sache immer noch ein Stück voraus.

Wenn viele parallele Abfragen gestartet werden, gehen Ihnen diese Arbeitsthreads aus. In diesem Fall warten Abfragen nur darauf, dass die Threads gestartet werden. Das ist auch der SOS_SCHEDULER_YIELDPunkt, an dem Abfragen die CPUs verlassen und lange nicht mehr weiterarbeiten. Ich sehe keine blockierenden Wartezeiten, daher sind Sie höchstwahrscheinlich nur überlastet, wenn es um abfrageinterne Parallelitätswarten geht.

Was kannst du tun?

  1. Stellen Sie sicher, dass sich nichts im Modus für ausgeglichene Stromversorgung befindet
  2. Ändern Sie MAXDOP in 2
  3. Ändern Sie den Kostenschwellenwert für Parallelität auf 50
  4. Befolgen Sie den obigen Artikel von Jon K., um den VM-Zustand zu überprüfen
  5. Verwenden Sie das aufgerufene Skript sp_BlitzIndex, um nach fehlenden Indexanforderungen zu suchen.

Weitere Informationen zur Fehlerbehebung finden Sie in dem Whitepaper, das ich für Google zum Thema Hardwaredimensionierung in der Cloud geschrieben habe.

Hoffe das hilft!



5

Eine Sache, auf die ich nicht hingewiesen habe, ist, dass das Hinzufügen von vCPUs zu einer VM aufgrund der Zeitplanung sehr häufig verlangsamt werden kann.

Die Grundidee ist, dass der Hypervisor bei einer VM mit 4 vCPUs darauf warten muss, dass 4 physische Kerne verfügbar sind, damit alle vCPUs geplant werden können, auch wenn drei davon inaktiv sind.

Wenn auf Ihrem Host nicht viele Kerne vorhanden sind und Ihre anderen Workloads ausgelastet sind, kann dies zu zusätzlichen Wartezeiten und einem erheblichen Leistungseinbruch führen.

In VMware ESXi können Sie es in den erweiterten Diagrammen über CPU Ready sehen.

Hier ist einer von vielen Artikeln mit einem realen Beispiel für dieses Ereignis und wie es diagnostiziert wurde .

Das Hinzufügen von mehr RAM kann auch zu einem plötzlichen Leistungseinbruch führen, wenn die RAM-Zuweisung der VM größer als ein NUMA-Knoten ist.

Darüber hinaus kann sich die Konfiguration Ihrer vCPUs (vSockets vs. vCores) auf einige Anwendungen wie SQL Server auswirken. Dies liegt daran, dass SQL Server selbst NUMA-fähig ist (um den gleichen NUMA-übergreifenden Leistungseinbruch zu vermeiden) und dass VMware virtuelle NUMA-Knoten möglicherweise unterschiedlich darstellt.

Dies wird in einem Blogbeitrag auf der VMware-eigenen Website behandelt .


Vor diesem Hintergrund bin ich froh, dass Sie die Probleme mit Eriks Hilfe gelöst haben, aber Sie möchten sich vielleicht auch diese Dinge ansehen und überlegen.


3

Nur eine kleine Hilfe (kann nicht als Kommentar gepostet werden) weiter @ sp_BlitzEriks Antwort, ich habe einige Fragen bei Pinal und Max Vernon (kann mich nicht erinnern, wo), die besagen, wie viel MAXDOP Sie verwenden sollten:

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

Das erste Skript gibt ein leeres Ergebnis zurück. Der zweite gibt einen Vorschlag zurück, MAXDOP = 2der mit @sp_BlitzErik übereinstimmt. Vielen Dank!
Jeff
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.