Algorytm ustawiania MAXDOP dla SQL Server

67

Podczas konfigurowania nowego programu SQL Server używam następującego kodu, aby określić dobry punkt wyjścia dla MAXDOPustawienia:

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


DECLARE @CoreCount int;
DECLARE @NumaNodes int;

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

IF @CoreCount > 4 /* If less than 5 cores, don't bother. */
BEGIN
    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));
END
ELSE
BEGIN
    PRINT 'Suggested MAXDOP = 0 since you have less than 4 cores total.';
    PRINT 'This is the default setting, you likely do not need to do';
    PRINT 'anything.';
END

Zdaję sobie sprawę, że jest to nieco subiektywne i może się różnić w zależności od wielu rzeczy; jednak próbuję stworzyć ciasny fragment kodu, który posłuży jako punkt wyjścia dla nowego serwera.

Czy ktoś ma jakieś dane wejściowe do tego kodu?

Max Vernon
źródło
1
Moja rekomendacja dla 4 procesorów domyślnie to 2. 0 ustawia na nieograniczoną. A kiedy już ustawiasz MAXDOP, zalecam rozważenie dostosowania progu kosztów dla równoległości (aka, CTFP) do wartości między 40 a 75. {Moje ulubione ustawienie początkowe to 42 ... z powodów, dla których wielu fanów Sci-Fi rozpoznać}
yeOldeDataSmythe
42 jest przecież odpowiedzią na wszystko. Ten post ma na przykład 42 tysiące wyświetleń.
Max Vernon

Odpowiedzi:

49

Najlepszym sposobem jest skorzystanie z Coreinfo (narzędzie od sysinternals), ponieważ da ci to

a. Logical to Physical Processor Map
b. Logical Processor to Socket Map
c. Logical Processor to NUMA Node Map as below :

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)
----------------**------  Physical Processor 8 (Hyperthreaded)
------------------**----  Physical Processor 9 (Hyperthreaded)
--------------------**--  Physical Processor 10 (Hyperthreaded)
----------------------**  Physical Processor 11 (Hyperthreaded)

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

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

Teraz, w oparciu o powyższe informacje, ustawienie Ideal MaxDop należy obliczyć jako

a.  It has 12 CPUs which are hyper threaded giving us 24 CPUs.
b.  It has 2 NUMA node [Node 0 and 1] each having 12 CPUs with Hyperthreading ON.
c.  Number of sockets are 2 [socket 0 and 1] which are housing 12 CPUs each.

Considering all above factors, the max degree of Parallelism should be set to 6 which is ideal value for server with above configuration.

Więc odpowiedź brzmi - „ to zależy ” od twojego procesora, a konfiguracja NUMA i poniższa tabela podsumują to, co wyjaśniłem powyżej:

8 or less processors    ===> 0 to N (where N= no. of processors)
More than 8 processors  ===> 8
NUMA configured         ===> MAXDOP should not exceed no of CPUs assigned to each 
                                 NUMA node with max value capped to 8
Hyper threading Enabled ===> Should not exceed the number of physical processors.

Edytowano: Poniżej znajduje się szybki i brudny skrypt TSQL do generowania zalecenia dla ustawienia 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

EDYCJA: Dla przyszłych gości, możesz spojrzeć na testową funkcję dbamaxdop PowerShell (wraz z innymi niezwykle pomocnymi funkcjami DBA (WSZYSTKO ZA DARMO !!).

Kin Shah
źródło
przypadku, gdy cpu_count> hyperthread_ratio, a następnie 1 jeszcze 0 koniec, czy jesteś pewien, że to prawda? ponieważ w przypadku 8 procesorów logicznych, 8 procesorów fizycznych i 1 jako hyperthread_ratio. wciąż mówi, że włączony jest hyperthread, w co trudno mi uwierzyć. W takim przypadku otrzymujesz również MAXDOP jako 1, co również nie brzmi prawdziwie.
UdIt Solanki
@UdItSolanki Prawidłowym sposobem jest użycie coreinfo w celu ustalenia, czy HT jest włączony, czy nie. Nie ma ostatecznego sposobu sprawdzenia, czy HT jest włączony przy użyciu TSQL. Próbowałeś, test-dbamaxdopjak wspomniano w mojej odpowiedzi?
Kin Shah
17

Podczas ustawiania MAXDOP zwykle chcesz ograniczyć go do liczby rdzeni w węźle NUMA. W ten sposób harmonogramy nie próbują uzyskać dostępu do pamięci między liczbami węzłów.

mrdenny
źródło
13

Patrząc na post z zespołu MSDN , wymyśliłem sposób, aby wiarygodnie uzyskać fizyczną liczbę rdzeni z maszyny i użyć go do określenia dobrego ustawienia MAXDOP.

Przez „dobry” mam na myśli konserwatystów. To znaczy, moim wymaganiem jest użycie maksymalnie 75% rdzeni w węźle NUMA lub ogólnie maksimum 8 rdzeni.

SQL Server 2016 (13.x) z dodatkiem SP2 i nowszym oraz wszystkie wersje SQL Server 2017 i powyżej zawierają szczegółowe informacje na temat liczby rdzeni fizycznych na gniazdo, liczby gniazd i liczby węzłów NUMA, co pozwala na uporządkowanie sposobu wyznaczania linii bazowej Ustawienie MAXDOP dla nowej instalacji SQL Server.

W przypadku wyżej wymienionych wersji ten kod zaleci konserwatywne ustawienie MAXDOP na poziomie 75% liczby fizycznych rdzeni w węźle NUMA:

DECLARE @socket_count int;
DECLARE @cores_per_socket int;
DECLARE @numa_node_count int;
DECLARE @memory_model nvarchar(120);
DECLARE @hyperthread_ratio int;

SELECT @socket_count = dosi.socket_count
       , @cores_per_socket = dosi.cores_per_socket
       , @numa_node_count = dosi.numa_node_count
       , @memory_model = dosi.sql_memory_model_desc
       , @hyperthread_ratio = dosi.hyperthread_ratio
FROM sys.dm_os_sys_info dosi;

SELECT [Socket Count] = @socket_count
       , [Cores Per Socket] = @cores_per_socket
       , [Number of NUMA nodes] = @numa_node_count
       , [Hyperthreading Enabled] = CASE WHEN @hyperthread_ratio > @cores_per_socket THEN 1 ELSE 0 END
       , [Lock Pages in Memory granted?] = CASE WHEN @memory_model = N'CONVENTIONAL' THEN 0 ELSE 1 END;

DECLARE @MAXDOP int = @cores_per_socket;
SET @MAXDOP = @MAXDOP * 0.75;
IF @MAXDOP >= 8 SET @MAXDOP = 8;

SELECT [Recommended MAXDOP setting] = @MAXDOP
       , [Command] = 'EXEC sys.sp_configure N''max degree of parallelism'', ' + CONVERT(nvarchar(10), @MAXDOP) + ';RECONFIGURE;';

W przypadku wersji programu SQL Server wcześniejszych niż SQL Server 2017 lub SQL Server 2016 SP2 nie można uzyskać liczby węzłów liczby rdzeni na liczbę sys.dm_os_sys_info. Zamiast tego możemy użyć programu PowerShell do ustalenia liczby fizycznych rdzeni:

powershell -OutputFormat Text -NoLogo -Command "& {Get-WmiObject -namespace 
"root\CIMV2" -class Win32_Processor -Property NumberOfCores} | select NumberOfCores"

Można również użyć programu PowerShell do określenia liczby rdzeni logicznych, która prawdopodobnie byłaby dwa razy większa niż liczba rdzeni fizycznych, jeśli HyperThreading jest włączony:

powershell -OutputFormat Text -NoLogo -Command "& {Get-WmiObject -namespace 
"root\CIMV2" -class Win32_Processor -Property NumberOfCores} 
| select NumberOfLogicalProcessors"

T-SQL:

/* 
   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));
Max Vernon
źródło
Uruchomiłem skrypt i polecił mi MAXDOP = 0. trudno uwierzyć dla 4 węzłów NUMA, enkalowane HT, procesory logiczne = 20 na 4 rdzenie. Masz pomysł, dlaczego?
BeginnerDBA
@BeginnerDBA - jakiej wersji programu SQL Server używasz?
Max Vernon
jego SQL Server 2012 i podobne w przypadku, gdy testowałem również na SQL2014
BeginnerDBA
Czy program SQL Server działa na maszynie wirtualnej? Wygląda na to, że liczba rdzeni na węzeł numa wynosi 1 - być może maszyna wirtualna jest dziwnie skonfigurowana? Możesz dodać to na końcu skryptu w celu debugowania: SELECT [@CoreCount] = @CoreCount , [@NumaNodes] = @NumaNodes , [@MaxDOP] = @MaxDOP
Max Vernon
dzięki. Nie, to serwer fizyczny, pozwólcie, że spróbuję to dodać
BeginnerDBA
11

Zasadniczo należy stosować wyższy DOP dla systemu OLAP i niższy (lub nie) DOP dla systemu OLTP. Wiele systemów znajduje się gdzieś pośrodku, więc znajdź szczęśliwy nośnik, który pozwala sporadycznie dużemu obciążeniu na uzyskanie wystarczającej ilości procesora do szybkiego ukończenia, bez duszenia obciążeń OLTP.

Uważaj także na użycie cpu_countkolumny, aby uzyskać liczbę rdzeni. Jeśli włączona jest funkcja hyperthreading, ta kolumna wydaje się odzwierciedlać liczbę ujawnionych procesorów logicznych. Ogólnie rzecz biorąc, nie chcesz, aby DOP był wyższy niż liczba rdzeni fizycznych. Rozłożenie dużego obciążenia równoległego na procesory logiczne po prostu zwiększy narzut bez rzeczywistych korzyści.

Jest też hyperthread_ratiokolumna, ale nie jestem pewien, co ona reprezentuje. Dokumentacja też nie jest zbyt jasna. Liczba, którą widzę w naszym systemie, sugeruje, że może to być albo liczba fizycznych rdzeni w całym systemie, albo liczba logicznych procesorów na układ. Dokumentacja twierdzi, że powinienem widzieć zupełnie inną postać.

db2
źródło
1
Uważam, że hyperthread_ratiojest to liczba rdzeni logicznych na procesor. Natknąłem się na to jakiś czas temu i jeśli dobrze pamiętam, do tego doszedłem. Może @AaronBertrand ma na ten temat więcej informacji. Nie bierz tego jednak za twardy i szybki fakt przed weryfikacją.
Thomas Stringer
@ThomasStringer dokumentacja stwierdza, że ​​i po uruchomieniu go na wielu komputerach, tak to wygląda. Jednak z tej kolumny trudno jest stwierdzić, czy hiperwątkowanie jest faktycznie włączone, czy nie. Na przykład na jednym z moich serwerów zgłasza 8 - serwer ma 2 fizyczne procesory, z 4 rdzeniami na każdym procesorze, z włączonym hyperthreading. Na komputerach bez hipertekstu zgłasza 4 w tych samych okolicznościach, ale bez ponownego uruchamiania (i wyłączania hipertekstu) nigdy nie zobaczysz tej zmiany!
Max Vernon
7

Natknąłem się również na artykuł http://support.microsoft.com/kb/2806535 i nie mogę znaleźć korelacji z powyższymi skryptami.

Zastanawiam się również, dlaczego istnieje rozróżnienie dla „@logicalCPUs> = 8 i @HTEnabled = 1 i @NoofNUMA = 1” oraz „@logicalCPUs> = 8 i @HTEnabled = 1 i @NoofNUMA> 1” w wyniku staje się taki sam.

W końcu napisałem własny fragment kodu pasujący do powyższego artykułu, chociaż nawet tam chciałbym bardziej precyzyjną definicję i / lub różnicę dotyczącą „procesorów”, „procesorów” i „procesorów fizycznych”.

Nie krępuj się.

/*************************************************************************
Author          :   Dennis Winter (Thought: Adapted from a script from "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
declare @MaxDOP 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

IF @NoofNUMA > 1 AND @HTEnabled = 0
    SET @MaxDOP= @logicalCPUPerNuma 
ELSE IF  @NoofNUMA > 1 AND @HTEnabled = 1
    SET @MaxDOP=round( @NoofNUMA  / @physicalCPU *1.0,0)
ELSE IF @HTEnabled = 0
    SET @MaxDOP=@logicalCPUs
ELSE IF @HTEnabled = 1
    SET @MaxDOP=@physicalCPU

IF @MaxDOP > 10
    SET @MaxDOP=10
IF @MaxDOP = 0
    SET @MaxDOP=1

PRINT 'logicalCPUs : '         + CONVERT(VARCHAR, @logicalCPUs)
PRINT 'hyperthreadingRatio : ' + CONVERT(VARCHAR, @hyperthreadingRatio) 
PRINT 'physicalCPU : '         + CONVERT(VARCHAR, @physicalCPU) 
PRINT 'HTEnabled : '           + CONVERT(VARCHAR, @HTEnabled)
PRINT 'logicalCPUPerNuma : '   + CONVERT(VARCHAR, @logicalCPUPerNuma) 
PRINT 'NoOfNUMA : '            + CONVERT(VARCHAR, @NoOfNUMA)
PRINT '---------------------------'
Print 'MAXDOP setting should be : ' + CONVERT(VARCHAR, @MaxDOP)
Dennis Winter
źródło
Niezły kawałek kodu. Nie jestem pewien, czy zdajesz sobie sprawę, że hyperthread_ratiokolumna sys.dm_os_sys_infojest myląca ... na przykład na mojej stacji roboczej mam na przykład pojedynczy 4-rdzeniowy procesor z włączonym hyperthreadingiem - Menedżer zadań widzi 8 logicznych procesorów, a Twój kod zgłasza stosunek hipertekstu do być 1.
Max Vernon
Jako FYI, mój kod generuje zalecenie 6 dla tej maszyny, co pozostawi 2 rdzenie dostępne nawet przy najbardziej stresujących równoległych zapytaniach.
Max Vernon
Hyperthread_ratio jest rzeczywiście problemem, choć nie można go lepiej rozwiązać - przynajmniej o ile mi wiadomo. Zobacz ten blog, aby uzyskać dodatkowe informacje: sqlblog.com/blogs/kalen_delaney/archive/2007/12/08/... A jeśli chodzi o twój drugi post - chciałbym wiedzieć, którego wartość dla „maksymalnego stopnia paraliżu” wybrałeś dla twojej maszyny. :-D Również jestem całkiem nowy w tym temacie - potknąłem się o to tylko dlatego, że nie wiedziałem wcześniej i potrzebowałem tych informacji. Jaki byłby zatem twój wniosek, czy 2 rdzenie są nadal dostępne, co jest dobre czy złe?
Dennis Winter
4

Ta wersja daje ładny pojedynczy zestaw wyników z istniejącym ustawieniem MAXDOP i powinna wytrzymać wersje SQL 2008-2017 bez potrzeby używania xp_cmdshell.

select
[ServerName]                    = @@SERVERNAME
, [ComputerName]                = SERVERPROPERTY('ComputerNamePhysicalNetBIOS') 
, [LogicalCPUs]             
, hyperthread_ratio 
, [PhysicalCPU]             
, [HTEnabled]               
, LogicalCPUPerNuma
, [NoOfNUMA]
, [MaxDop_Recommended]          = convert(int,case when [MaxDop_RAW] > 10 then 10 else [MaxDop_RAW] end)
, [MaxDop_Current]              = sc.value
, [MaxDop_RAW]
, [Number of Cores] 
from
(
select
     [LogicalCPUs]              
    , hyperthread_ratio 
    , [PhysicalCPU]             
    , [HTEnabled]               
    , LogicalCPUPerNuma
    , [NoOfNUMA]
    , [Number of Cores] 
    , [MaxDop_RAW]              = 
        case
            when [NoOfNUMA] > 1 AND HTEnabled = 0 then logicalCPUPerNuma 
            when [NoOfNUMA] > 1 AND HTEnabled = 1 then convert(decimal(9,4),[NoOfNUMA]/ convert(decimal(9,4),Res_MAXDOP.PhysicalCPU) * convert(decimal(9,4),1))
            when HTEnabled = 0 then  Res_MAXDOP.LogicalCPUs
            when HTEnabled = 1 then  Res_MAXDOP.PhysicalCPU
        end
from
(
    select
         [LogicalCPUs]              = osi.cpu_count
        , osi.hyperthread_ratio 
        , [PhysicalCPU]             = osi.cpu_count/osi.hyperthread_ratio
        , [HTEnabled]               = case when osi.cpu_count > osi.hyperthread_ratio then 1 else 0 end
        , LogicalCPUPerNuma
        , [NoOfNUMA]
        , [Number of Cores] 
    from 
    (
        select
            [NoOfNUMA]  = count(res.parent_node_id)
            ,[Number of Cores]  = res.LogicalCPUPerNuma/count(res.parent_node_id)
            ,res.LogicalCPUPerNuma
        from
        (
            Select
                s.parent_node_id
                ,LogicalCPUPerNuma  = count(1)
            from
                sys.dm_os_schedulers s
            where
                s.parent_node_id < 64
                and
                s.status = 'VISIBLE ONLINE'
            group by 
                s.parent_node_id
        ) Res
        group by
            res.LogicalCPUPerNuma
    ) Res_NUMA
    cross apply sys.dm_os_sys_info osi
) Res_MAXDOP
)Res_Final
cross apply sys.sysconfigures sc
where sc.comment = 'maximum degree of parallelism'
option (recompile);
ShadowDancerLV
źródło
3

Fajny skrypt, ale artykuł KB: http://support.microsoft.com/kb/2806535 nie jiwuje całkowicie z twoim kodem. czego mi brakuje?

Server 1
HTEnabled: 1
hyperthreading Relation: 12
logical cpus: 24
physical cpus: 2
logical cpus per numa: 12
NoOfNuma: 2
MaxDop powinno być: 6

Server 2
HTEnabled: 2
hyperthreadingRatio: 16
logical cpus: 64
fizyczny cpus: 4
logiczny cpus na liczba: 16
NoOfNuma: 4
Ustawienie MaxDop powinno wynosić: 4

Zdaję sobie sprawę, że to tylko sugestie; ale coś mi się nie wydaje, że serwer (# 2) powyżej z 4 procesorami zamiast 2 i 8 rdzeniami na fizyczny procesor zamiast 6; poleciłby MAXDOP na 4, w porównaniu do 6 dla słabszego serwera.

Powyższy artykuł kbb sugeruje 8 mój scenariusz powyżej. „W przypadku serwerów, które mają skonfigurowaną NUMA i włączoną funkcję Hyperthreading, wartość MAXDOP nie powinna przekraczać liczby fizycznych procesorów na węzeł NUMA.”

Bob McC
źródło
Jeśli ustawisz MAXDOP na wyższą niż liczba rdzeni / węzłów numa, skończysz z połączeniami w dalekiej pamięci, które są wielokrotnie wielokrotnie wolniejsze niż w pobliżu pamięci. Jest tak, ponieważ każdy węzeł numa ma własną pamięć; zapytanie wykorzystując więcej wątków niż jest obecnych w trybie pojedynczej liczby, rozłoży obciążenie procesora na wiele rdzeni, a zatem na wiele węzłów pamięci.
Max Vernon
Zalecam ustawienie MAXDOP na ustawienie, które ma sens dla serwera, który uruchamia obciążenie. Tylko Ty możesz określić najlepsze ustawienie dla konkretnego obciążenia; ten post jest jedynie wskazówką.
Max Vernon