Mantıklı bir tampon havuzu boyutunu değerlendirmek için deterministik bir yöntem nedir?


29

max server memory (mb)Ayarın uygun olup olmadığını anlamak için akıllıca bir yol bulmaya çalışıyorum (ya daha düşük ya da daha yüksek olmalı ya da olduğu gibi kal). max server memory (mb)İşletim sisteminin kendisine vb. Yer bırakacak kadar düşük olması gerektiğinin farkındayım .

Baktığım ortamın birkaç yüz sunucusu var; Tampon havuzunun mevcut boyutunun uygun olup olmadığını belirlemek için kullanabileceğim güvenilir bir formüle ihtiyacım var çünkü RAM her sunucuya tahsis edilen GB başına maliyete mal oluyor. Tüm ortam sanallaştırılmış ve bir VM'ye tahsis edilen "fiziksel" RAM kolayca yukarı veya aşağı değiştirilebilir.

Şu anda belirli bir SQL Server Örneğine sahibim, şu anda 1.100.052 saniyelik bir PLE ile bakıyorum, bu da 12.7 güne (sunucunun çalışma süresi) eşittir. Sunucu, yalnızca 1380 MB (1,3 GB) gerçekten taahhüt edilen 2560 MB (2,5 GB) kapasiteli bir maksimum bellek belleği ayarına sahiptir.

Biri Jonathan Keheyias ( post ), diğeri Paul Randal ( post ) ve diğerleri de dahil olmak üzere birkaç madde okudum . Jonathan, 4GB tampon havuzu başına 300'ün altındaki bir PLE'nin izlenmesinin çok düşük olduğunu savunuyor . Yukarıdaki SQL Server Örneği için, 300 * (2.5 / 4) = 187300'ün altındaki gerçekten düşük bir hedef PLE ile sonuçlanır. Bu örnekte, 290 GB SQL Server verisi vardır (günlük dosyaları dahil değil) ve yalnızca tümleştirme testi için kullanılır. Son 12 gün varsayarsak bu sunucu için tipik kullanım temsilcisidir diyebilirim max server memory (mb)ayar olabilir düşürülmelidir.

Ölçeğin diğer ucunda, 294 PLE'ye sahip max server memory (mb), yalnızca 1 GB ayarına sahip başka bir tümleştirme testi sunucum var . Bu sunucu, günlükleri içermeyen yalnızca 224 MB SQL Server verisine sahiptir ve bazı BizFlow veritabanlarını çalıştırmaktadır. Bu sunucu olabilir , daha yüksek fayda max server memory (mb)ayarı.

Çok fazla bellek atanabilecek hedefler için iyi bir başlangıç ​​noktası olduğunu düşünüyorum.

SELECT 
    RamMB = physical_memory_in_bytes / 1048576
    , BufferPoolCommittedMB = bpool_committed * 8192E0 / 1048576
    , BufferPoolCommitTargetMB = bpool_commit_target * 8192E0 / 1048576
    , PercentOfDesiredSizeMB = CONVERT(INT,(CONVERT(DECIMAL(18,2),bpool_committed) 
                            / bpool_commit_target) * 100)
FROM sys.dm_os_sys_info;

Eğer BufferPoolCommitTargetMB / BufferPoolCommittedMB1'den büyük olduğu, sunucu tüm tampon havuzu kullanmıyor. Söz konusu makine aynı zamanda "x" den daha büyük bir PLE'ye sahipse, o zaman bir düşüş için iyi bir aday olabilir max server memory (mb).

Yana Buffer Manager:Lazy writes/secperformans sayacı nedeniyle bellek baskısı SQLOS sınır kapısı arasındaki diske dışarı sayfaları yazmış sayısını gösterir, bu bakmak için başka iyi bir şey olabilir.

DECLARE @WaitTime DATETIME;
SET @WaitTime = '00:00:15';
DECLARE @NumSeconds INT;
SET @NumSeconds = DATEDIFF(SECOND, 0, @WaitTime);
DECLARE @LazyWrites1 BIGINT;
DECLARE @LazyWrites2 BIGINT;

SELECT @LazyWrites1 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE 'Lazy writes/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = 'MSSQL$' + CONVERT(VARCHAR(255),
               SERVERPROPERTY('InstanceName')) + ':Buffer Manager';

WAITFOR DELAY @WaitTime;

SELECT @LazyWrites2 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE 'Lazy writes/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = 'MSSQL$' + CONVERT(VARCHAR(255),
               SERVERPROPERTY('InstanceName')) + ':Buffer Manager';

SELECT LazyWritesPerSecond = (@LazyWrites2 - @LazyWrites1) / @NumSeconds;

Yukarıdaki kod sunucunun çalışması 15 saniye boyunca yük altında olduğunu varsayar, aksi takdirde 0 bildirir; yanıltıcı, yanlış-negatif olabilir.

PAGELATCHIO_*Bekleme istatistiklerine veya başka bir bekleme türüne de bellek baskısının bir göstergesi olarak mı bakmalıyım ?

Sorum şu ki, PLE ve için "iyi" bir hedef değeri nasıl güvenilir bir şekilde belirleyebilirim max server memory (mb)?

Yanıtlar:


11

Zaten bildiğiniz gibi, maksimum sunucu belleğini hesaplamak için genel bir formül yoktur, bazı hızlı matematik işlemleri yapabilir ve bir değere erişebilirsiniz ancak yine de bellek kullanımını izlemek ve buna bağlı olarak değişiklik yapmak için en son Perfmon sayaçlarının yardımına ihtiyacınız olacaktır. Aşağıdaki genel formülü biliyorum ve onu da kullanıyorum. Bu formülü This Link'ten öğrendim.

SQL Server 2005 ila 2008 R2 için

Lütfen SQL Server 2005'ten 2008'e kadar olan R2 maksimum sunucu belleğinin sadece tampon havuzunu kontrol ettiğini unutmayın. Yani maksimum sunucu belleği konfigürasyonu burada biraz sıkıcı ve az hesaplama gerektirir

  1. Windows işletim sistemi için 2 G belleği hemen bırakın.

  2. Tabii ki sistem çalışan antivirüs olurdu. Lütfen Antivirus için 1.5G bırakın. Lütfen Mcafee ve SQL Server'ın el ele girmediğini unutmayın, bu nedenle bunun için yeterli zaman ayırdığınızdan emin olun. Ayrıca Perfmon Process-> Private bytes and Working SetAV kullanımını ve SQL Server kutusundaki diğer küçük uygulamaları kullanarak bellek kullanımını izlemek için perfmon sayacını da kontrol edebilirsiniz.

görüntü tanımını buraya girin

  1. Sürücülerin / bellenimlerin bellek gereksinimlerini göz önünde bulundurun. Bunu, sistemde yüklü sürücüler tarafından bellek gereksinimlerine göre türetmelisiniz. RAMMAP aracı yardımcı olabilir

  2. SQL Server'ın NonbPool (aka MTL veya MTR) bellek gereksinimlerini göz önünde bulundurun.

    select  sum(multi_pages_kb)/1024 as multi_pages_mb from  sys.dm_os_memory_clerks

    + Maksimum işçi iş parçacığı * 2 MB

    + Doğrudan Windows tahsisi için bellek çoğu durumda yaklaşık 0 - 300 MB'dir, ancak SQL Server işleminde yüklenen çok sayıda 3 parti bileşen varsa (bağlı sunucu dll'ler, 3. parti yedekleme dll'ler vb. Dahil) arttırmanız gerekebilir.

    + Eğer CLR'yi kullanıyorsanız, CLR için ek bir hafıza ekleyin.

  3. Bellek gereksinimini işlerde (çoğaltma aracıları, Günlük gönderimi vb. Dahil) ve sunucuda çalışacak paketler tarafından değerlendirin. Çalışan iş sayısına göre MB'den GB'ye kadar olabilir. Orta boy bir sunucu için 250 MB olarak alabilir

  4. İşletim sistemi için yeterince boş alan olduğundan emin olun.

    Yaklaşık (4 GB'a kadar her GB için 100 MB) + (12 GB'a kadar her ilave GB için 50 MB) + (RAM boyutuna kadar her ilave GB için 25 MB)

  5. Diğer hafıza gereksinimleri.

    Ortamınıza özel başka bir bellek gereksiniminiz varsa.

    Maksimum sunucu belleği = Toplam fiziksel bellek - (1 + 2 + 3 + 4 + 5 + 6 + 7)

    SSIS.SSRS için bellek yapılandırmasını dahil etmedim, SSAS ayrıca bu servislerin gerektirdiği belleği toplam fiziksel sunucu belleğinden çıkarmanız gerekir.

    Yukarıda yapılandırdıktan sonra aşağıdaki sayaçları izlemeniz gerekir

  • SQLServer: Buffer Manager - Sayfa Ömrü Beklentisi (PLE):

  • SQLServer: Arabellek Yöneticisi - CheckpointPages / sn:

  • SQLServer: Bellek Yöneticisi - Bekleyen Bellek Hibeleri:

  • SQLServer: bellek Yöneticisi - Hedef Sunucu Belleği:

  • SQLServer: bellek Yöneticisi - Toplam Sunucu belleği

SQL Server 2012/2014 için.

From SQL Server 2012 onwardsmaksimum sunucu belleği ayarlamak kolaylaştı. Çünkü şimdi maksimum sunucu belleği neredeyse tüm bellek tüketimini hesaba katar. En fazla sunucu belleği, arabellek havuzu, derleme belleği, tüm önbellek, qe bellek desteği, kilit yöneticisi belleği ve CLR belleği de dahil olmak üzere SQL Server bellek tahsisini kontrol eder (temelde dm_os_memory_clerks içinde bulunan herhangi bir "katip"). İş parçacığı yığınları, yığınları, SQL Server dışındaki bağlantılı sunucu sağlayıcıları veya “SQL Server olmayan” bir DLL tarafından ayrılan herhangi bir bellek için maksimum sunucu belleği tarafından kontrol edilmez.

% 75-80'i SQL Server'a tahsis edebilir ve ardından bellek kullanımını izlemek için perfmon sayaçlarını kullanabilirsiniz. SQL Server 2012'de, bazı perfmon sayaçları kullanımdan kaldırılmıştır. Arabellek yöneticisi sayacı kullanımdan kaldırıldı Bellek yöneticisi sayacını kullanmanız gerekir

  • SQL Server: Bellek Yöneticisi - Hedef Sunucu Belleği (KB)

  • SQL Server: Bellek Yöneticisi - Toplam Sunucu Belleği (KB)

  • SQL Server: Bellek Yöneticisi - Boş Bellek (KB)

  • SQL Server: Bellek Yöneticisi - Veritabanı Önbellek Belleği (KB)

PLE'nin değerine göre, Joanthan'ın formülünü kullandım ve neyse ki benim için çalıştı.


6

Buradaki zorluk, rakamların son kullanıcı deneyimini hesaba katmamasıdır.

Mükemmel örnek: Şirket çalışanlarının ziyaret ettiği her web sitesini izlemek için kullanılan veritabanı sunucum var. Ön uç uygulaması ekleri periyodik olarak ayırdığından ve yavaş ekler kullanıcılar için bir sorun oluşturmaz, çünkü yoğun yükler sırasında kesici uçlara ayak uydurabilmesi umurumda değil. Kullanıcılar yavaş uçlar tarafından tutulmadan internette sörf yapabilir.

SELECT zamanında, İK departmanı belirli bir çalışan için şüpheli tarama geçmişi sorulduğunda raporları ateşler, ancak raporların ne kadar sürdüğünü önemsemezler - sadece raporu açarlar ve başka şeyler yapmaya giderler.

Performans bir soru ile başlamalıdır: Kullanıcılar performanstan memnun mu? Eğer öyleyse, sistemi olduğu yerde bırakın.


İhtiyacınız olandan daha fazla hafıza kullanıyor olsanız bile?
James Anderson

2
James - genel olarak konuşursak, kullanıcıların şikayet etmesine neden olacak değişiklikler yapmak istemiyorum. Bunu yapmak istiyorsanız, kullanıcılar şikayet etmeye başlayana kadar her sunucu için bellek miktarını aşamalı olarak azaltabilirsiniz, ancak zaten çok çalıştığımda, genellikle bu adımları atmaya zamanım yok. Mutsuz kullanıcıları mutlu edecek işlere odaklanmalıyım - mutlu kullanıcıları mutsuz etmeye çalışmak yerine. ;-)
Brent Ozar

2
İyi puanlar Brent. Bazı sunucuların aşırı tedarik edilip edilmediğini sormam istendi, çünkü her yıl GB başına bellek ödediğimiz için. Baktığım örneklerin çoğu, çok az miktarda RAM olarak düşündüğüm şeye sahip max server memory (mb)ve bu yüzden onları küçültmek konusunda oldukça isteksizim. Bununla birlikte, diğer bazı örnekler 1.000.000 + PLE'ye sahiptir ve bu nedenle RAM'deki bir düşüş için oldukça belirgin potansiyel adaylardır. Açıkçası, RAM düşürücü IOPS artışa neden olur, ve eminim maliyeti nedir değilim o olacaktır.
Max Vernon

1
Ayrıca, PLE'ye bakıldığında, max server memoryayara göre bir tür tavuk ve yumurta işi; düşürmek max server memoryBen sürekli düşürücü sarmal içinde sıkışıp böylece minimum "kabul edilebilir" PLE olacağını düşürmek, ayarı. Eminim, bahsettiğiniz gibi, kullanıcı performansı bir noktada etkilenecektir.
Max Vernon

PLE sayaçları, 2012'den itibaren bakmaktan kaçınmanız gereken veya her düğümün kendi küçük bellek ayırıcısı olarak davrandığı NUMA sisteminiz olduğunda bir tanesidir. İsterseniz tamamlanmamış her bir NUMA düğümü için
PLE'yi aramalısınız

3

PLE vs değerlendirmek için kullanıyorum geçerli T-SQL max server memory:

/*
    Purpose:            Returns a resultset describing various server level stats including PLE
                        Max and Min Server Memory, etc.
    By:                 Max Vernon
    Date:               2014-12-01
*/
SET NOCOUNT ON;

/*
    wait stats for PAGELATCH_IO
*/
DECLARE @Debug BIT;
SET @Debug = 0;
DECLARE @HTMLOutput BIT;
SET @HTMLOutput = 1;
DECLARE @WaitTime DATETIME;
SET @WaitTime = '00:00:15';
DECLARE @NumSeconds INT;
SET @NumSeconds = DATEDIFF(SECOND, 0, @WaitTime);
DECLARE @InstanceName NVARCHAR(255);
SET @InstanceName = CONVERT(NVARCHAR(255), SERVERPROPERTY('InstanceName'));
DECLARE @Version NVARCHAR(255);
DECLARE @VersionINT INT;
SET @Version = CONVERT(NVARCHAR(255),SERVERPROPERTY('ProductVersion'));
SET @VersionINT = CONVERT(INT, SUBSTRING(@Version,1 ,CHARINDEX('.',@Version)-1));
DECLARE @cmd NVARCHAR(MAX);
SET @cmd = '';
DECLARE @TaskCount INT;
DECLARE @TasksPerSecondAvg INT;
DECLARE @AvgWaitTimeInMSPerTask DECIMAL(10,2);
DECLARE @AvgWaitTimeInMSPerSecond DECIMAL(10,2);
DECLARE @TotalWaitTimeInMSOverall DECIMAL(10,2);
DECLARE @LazyWrites1 BIGINT;
DECLARE @LazyWrites2 BIGINT;
DECLARE @FreeListStallsSec1 BIGINT;
DECLARE @FreeListStallsSec2 BIGINT;
DECLARE @BatchReq1 BIGINT;
DECLARE @BatchReq2 BIGINT;
DECLARE @ws TABLE
(
    RunNum INT
    , wait_type SYSNAME
    , waiting_tasks_count BIGINT
    , wait_time_ms BIGINT
    , max_wait_time_ms BIGINT
    , signal_wait_time_ms BIGINT
);
INSERT INTO @ws
SELECT 1, dows.*
FROM sys.dm_os_wait_stats dows
WHERE dows.wait_type LIKE 'PAGEIOLATCH_%'
ORDER BY dows.waiting_tasks_count DESC;

SELECT @LazyWrites1 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE N'Lazy writes/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':Buffer Manager';

SELECT @FreeListStallsSec1 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE N'Free list stalls/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':Buffer Manager';

SELECT @BatchReq1 = cntr_value
FROM sys.dm_os_performance_counters dopc
WHERE dopc.counter_name LIKE N'Batch Requests/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':SQL Statistics';

WAITFOR DELAY @WaitTime;

INSERT INTO @ws
SELECT 2, dows.*
FROM sys.dm_os_wait_stats dows
WHERE dows.wait_type LIKE N'PAGEIOLATCH_%'
ORDER BY dows.waiting_tasks_count DESC;

SELECT @LazyWrites2 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE N'Lazy writes/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':Buffer Manager';

SELECT @FreeListStallsSec2 = cntr_value 
FROM sys.dm_os_performance_counters dopc
WHERE (
        dopc.counter_name LIKE N'Free list stalls/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    )
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':Buffer Manager';

SELECT @TaskCount = SUM(w2.waiting_tasks_count - w1.waiting_tasks_count)
    , @TasksPerSecondAvg = CONVERT(DECIMAL(10,2), (SUM(w2.waiting_tasks_count) - SUM(w1.waiting_tasks_count))) / @NumSeconds
    , @AvgWaitTimeInMSPerTask = CONVERT(DECIMAL(10,2),(SUM(w2.wait_time_ms) - SUM(w1.wait_time_ms))) / CONVERT(DECIMAL(10,2),(SUM(w2.waiting_tasks_count) - SUM(w1.waiting_tasks_count)))
    , @AvgWaitTimeInMSPerSecond = (CONVERT(DECIMAL(10,2), (SUM(w2.waiting_tasks_count) - SUM(w1.waiting_tasks_count))) / @NumSeconds) * (CONVERT(DECIMAL(10,2),(SUM(w2.wait_time_ms) - SUM(w1.wait_time_ms))) / CONVERT(DECIMAL(10,2),(SUM(w2.waiting_tasks_count) - SUM(w1.waiting_tasks_count))))
    , @TotalWaitTimeInMSOverall = SUM(w2.wait_time_ms) - SUM(w1.wait_time_ms)
FROM (SELECT * FROM @ws ws1 WHERE ws1.RunNum = 1) w1
    INNER JOIN (SELECT * FROM @ws ws2 WHERE ws2.RunNum = 2) w2 ON w1.wait_type = w2.wait_type
WHERE (w2.waiting_tasks_count - w1.waiting_tasks_count) > 0;

SELECT @BatchReq2 = cntr_value
FROM sys.dm_os_performance_counters dopc
WHERE dopc.counter_name LIKE N'Batch Requests/sec%' COLLATE SQL_Latin1_General_CP1_CI_AS
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':SQL Statistics';

/*
    configured values for max server memory and min server memory, etc
*/
DECLARE @MaxServerMemory BIGINT;
DECLARE @MaxServerMemoryPages BIGINT;
DECLARE @MinServerMemory BIGINT;
DECLARE @MinPLE BIGINT;
DECLARE @RamMB BIGINT;
DECLARE @BufferPoolCommittedMB BIGINT;
DECLARE @BufferPoolCommitTargetMB BIGINT;
DECLARE @PercentOfDesiredSizeMB INT;
DECLARE @TargetPageLifeExpectancyPer4GB BIGINT;
SET @TargetPageLifeExpectancyPer4GB = 60 * 120; /* 120 minutes */
/*DECLARE @VMType VARCHAR(255);*/
DECLARE @PLESeconds BIGINT;

SELECT @MaxServerMemory = CONVERT(BIGINT,c.value)
FROM sys.configurations c
WHERE c.name = N'max server memory (mb)'

SET @MaxServerMemoryPages = @MaxServerMemory / 128; /* 8KB pages */

SELECT @MinServerMemory = CONVERT(BIGINT,c.value)
FROM sys.configurations c
WHERE c.name = N'min server memory (mb)'

SET @MinPLE = @MaxServerMemory / 4096E0 * @TargetPageLifeExpectancyPer4GB;

IF @VersionINT < 11
BEGIN
    SET @cmd = 'SELECT 
    @RamMB = dosi.physical_memory_in_bytes / 1048576
    , @BufferPoolCommittedMB = dosi.bpool_committed * 8192E0 / 1048576
    , @BufferPoolCommitTargetMB = dosi.bpool_commit_target * 8192E0 / 1048576
    , @PercentOfDesiredSizeMB = CONVERT(INT,(CONVERT(DECIMAL(18,2),dosi.bpool_committed) / dosi.bpool_commit_target) * 100)
FROM sys.dm_os_sys_info dosi;
';
END
ELSE 
BEGIN 
SET @cmd = 'SELECT 
    @RamMB = dosi.physical_memory_kb / 1024
    , @BufferPoolCommittedMB = dosi.committed_kb / 1024
    , @BufferPoolCommitTargetMB = dosi.committed_target_kb / 1024
    , @PercentOfDesiredSizeMB = CONVERT(INT,(CONVERT(DECIMAL(18,2),dosi.committed_kb) / dosi.committed_target_kb) * 100)
FROM sys.dm_os_sys_info dosi;';
END
EXEC sp_executesql @cmd
    , N'@RamMB BIGINT OUTPUT, @BufferPoolCommittedMB BIGINT OUTPUT, @BufferPoolCommitTargetMB BIGINT OUTPUT, @PercentOfDesiredSizeMB INT OUTPUT' 
    , @RamMB = @RamMB OUT
    , @BufferPoolCommittedMB = @BufferPoolCommittedMB OUT
    , @BufferPoolCommitTargetMB = @BufferPoolCommitTargetMB OUT
    , @PercentOfDesiredSizeMB = @PercentOfDesiredSizeMB OUT;

/*
    Page Life Expectancy for all memory nodes
*/
SELECT @PLESeconds = CONVERT(BIGINT, cntr_value) 
FROM sys.dm_os_performance_counters dopc
WHERE dopc.counter_name LIKE N'Page Life Expectancy%' COLLATE SQL_Latin1_General_CP1_CI_AS
    AND dopc.object_name = N'MSSQL$' + @InstanceName + N':Buffer Manager';

/*
    Total data in all user-databases.
*/
DECLARE @TotalDBSpaceUsed TABLE
(
    TotalSpaceUsedInMB BIGINT
);
DECLARE @SpaceUsedInMB BIGINT;
SET @cmd = '';
SELECT @cmd = @cmd + CASE WHEN @cmd = '' THEN '' ELSE '
UNION ALL
' END + 
'
SELECT DatabaseName = ''' + d.name + ''' 
    , AllocType = au.type_desc
    , TotalPagesInMB = SUM(au.total_pages) * 8192E0 / 1048576
FROM ' + QUOTENAME(d.name) + '.sys.allocation_units au
WHERE au.type > 0
GROUP BY au.type_desc
'
FROM master.sys.databases d
WHERE d.database_id > 4;
SET @cmd = 'SELECT SUM(TotalPagesInMB)
FROM (
' + @cmd + '
) t;'; 
INSERT INTO @TotalDBSpaceUsed (TotalSpaceUsedInMB)
EXEC sp_executesql @cmd;
SELECT @SpaceUsedInMB = TDSU.TotalSpaceUsedInMB
FROM @TotalDBSpaceUsed TDSU;

IF @Debug = 1
BEGIN
    SELECT ServerName = @@SERVERNAME
        , InstanceName = @InstanceName
        , DatabaseSpaceUsedMB = @SpaceUsedInMB
        , PLEinSeconds = @PLESeconds
        , MinAcceptablePLE = @MinPLE
        , MinServerMemoryMB = @MinServerMemory
        , MaxServerMemoryMB = @MaxServerMemory
        , TotalServerRAMinMB = @RamMB
        , BufferPoolCommittedMB = @BufferPoolCommittedMB
        , BufferPoolCommitTargetMB = @BufferPoolCommitTargetMB
        , PercentBufferPoolCommitted = @PercentOfDesiredSizeMB
        , BatchReqPerSecond = (@BatchReq2 - @BatchReq1) / @NumSeconds
        , LazyWritesPerSecond = (@LazyWrites2 - @LazyWrites1) / @NumSeconds
        , FreeListStallsPerSecond = (@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds
        /*, VMType = @VMType*/
        , IOTaskCount = @TaskCount 
        , TaskPerSecondAvg = @TasksPerSecondAvg 
        , AvgWaitTimeInMSPerTask = @AvgWaitTimeInMSPerTask 
        , AvgWaitTimeInMSPerSecond = @AvgWaitTimeInMSPerSecond 
        , TotalWaitTimeInMSOverall  = @TotalWaitTimeInMSOverall
        , SamplePeriodinSec = @NumSeconds;

    SELECT MaxServerMemorySuggested = 
            CASE WHEN @BufferPoolCommittedMB < @BufferPoolCommitTargetMB 
            THEN @BufferPoolCommittedMB 
            ELSE ((CONVERT(DECIMAL(18,4), @MinPLE) / @PLESeconds) * @MaxServerMemory) 
                    + (((@LazyWrites2 - @LazyWrites1) / @NumSeconds) * 64) 
                    + ((@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds) * 64 
            END
        , Reason = CASE WHEN @BufferPoolCommittedMB < @BufferPoolCommitTargetMB THEN N'Committed MB less than current Max Server Memory'
            ELSE N'Calculated based on PLE, Lazy Writes / second and List Stalls / second' END
        , LazyWritesX64 = (((@LazyWrites2 - @LazyWrites1) / @NumSeconds) * 64)
        , ListStallsX64 = ((@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds) * 64;
END

DECLARE @Out TABLE
(
    KeyID INT IDENTITY(1,1)
    , ItemDesc NVARCHAR(255)
    , ItemValue SQL_VARIANT
    , IsDebug BIT DEFAULT(0)
);

INSERT INTO @Out (ItemDesc, ItemValue, IsDebug)
VALUES (N'Server Name', CONVERT(NVARCHAR(255),@@SERVERNAME), 1);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Data Space Used (MB)', @SpaceUsedInMB);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Page Life Expectancy (sec)', @PLESeconds);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Minimum Acceptable Page Life Expectancy (sec)', @MinPLE);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Minimum Server Memory (MB)', @MinServerMemory);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Maximum Server Memory (MB)', @MaxServerMemory);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Total Server RAM in MB', @RamMB);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Buffer Pool Committed MB', @BufferPoolCommittedMB);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Buffer Pool Commit Target MB', @BufferPoolCommitTargetMB);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Percent of Buffer Pool Committed', @PercentOfDesiredSizeMB);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Batch Requests Per Second', (@BatchReq2 - @BatchReq1) / @NumSeconds);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Lazy Writes Per Second', (@LazyWrites2 - @LazyWrites1) / @NumSeconds);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Free List Stalls Per Second', (@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'IO Task Count', @TaskCount);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Task Per Second Avg', @TasksPerSecondAvg);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Avg Wait Time In MS Per Task', @AvgWaitTimeInMSPerTask);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Avg Wait Time In MS Per Second', @AvgWaitTimeInMSPerSecond);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Total Wait Time In MS Overall', @TotalWaitTimeInMSOverall);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Sample Period in Seconds', @NumSeconds);

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Lazy Writes per Second', ((@LazyWrites2 - @LazyWrites1) / @NumSeconds));

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'List Stalls per Second', ((@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds));

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Recommended Max Memory (MB)', N'');

INSERT INTO @Out (ItemDesc, ItemValue)
VALUES (N'Recommended Max Memory Reason', N'');

INSERT INTO @Out (ItemDesc, ItemValue, IsDebug)
VALUES (N'Recommended Max Memory Signal', 0, 1);

/*
    Add memory if Lazy Writes occurred
    Add 64MB per Lazy Write (just for fun)
*/
DECLARE @LazyWritesMB INT;
SET @LazyWritesMB = (((@LazyWrites2 - @LazyWrites1) / @NumSeconds) * 64);

/*
    Add memory if Free List Stalls occurred
    Add 128MB per Free List Stall
*/
DECLARE @FreeListStallMB INT;
SET @FreeListStallMB = (((@FreeListStallsSec2 - @FreeListStallsSec2) / @NumSeconds) * 128);

/*
    Add the Additional memory requirements to the Recommended Max Memory row
*/
DECLARE @AdditionalMemory INT;
SET @AdditionalMemory = 
    @LazyWritesMB
    + @FreeListStallMB;

IF (@MaxServerMemory + @AdditionalMemory < 1024) AND (@PLESeconds >= @MinPLE)
BEGIN
    UPDATE @Out 
    SET ItemValue = @MaxServerMemory
    WHERE ItemDesc = N'Recommended Max Memory (MB)';

    UPDATE @Out 
    SET ItemValue = 'Max Server Memory is low, however PLE is acceptable'
    WHERE ItemDesc = N'Recommended Max Memory Reason';

    UPDATE @Out 
    SET ItemValue = 1
    WHERE ItemDesc = N'Recommended Max Memory Signal';
END

IF ((@BufferPoolCommittedMB + @AdditionalMemory) < @BufferPoolCommitTargetMB) AND (@PLESeconds >= @MinPLE)
BEGIN
    UPDATE @Out 
    SET ItemValue = @BufferPoolCommittedMB + @AdditionalMemory
    WHERE ItemDesc = N'Recommended Max Memory (MB)';

    UPDATE @Out 
    SET ItemValue = 'Buffer pool committed is less than Max Server Memory, and PLE is acceptable.'
    WHERE ItemDesc = N'Recommended Max Memory Reason';

    UPDATE @Out 
    SET ItemValue = 2
    WHERE ItemDesc = N'Recommended Max Memory Signal';
END

DECLARE @PLEMultiplier DECIMAL(10,2);
SET @PLEMultiplier = (CONVERT(DECIMAL(10,2),@MinPLE) / CONVERT(DECIMAL(10,2), @PLESeconds));
IF @PLEMultiplier < 0.90 SET @PLEMultiplier = 0.90;
IF @PLEMultiplier > 1.10 SET @PLEMultiplier = 1.10;

INSERT INTO @Out (ItemDesc, ItemValue, IsDebug)
VALUES (N'PLE Multiplier', @PLEMultiplier, 1);

IF /*(@MaxServerMemory + @AdditionalMemory >= 1024) AND*/ (@PLESeconds <= @MinPLE)
BEGIN
    UPDATE @Out 
    SET ItemValue = 
        (SELECT TOP(1) Inc
        FROM (
            SELECT Inc = t.RowNum * 256
            FROM (
                SELECT RowNum = CONVERT(BIGINT,ROW_NUMBER() OVER (ORDER BY o.object_id))
                FROM sys.objects o, sys.objects o1
                ) t
            WHERE (t.RowNum * 256) <  CONVERT(BIGINT,POWER(2,30))
            ) t1
        WHERE t1.Inc > CONVERT(INT, (@MaxServerMemory * @PLEMultiplier))
        ORDER BY t1.Inc)
    WHERE ItemDesc = N'Recommended Max Memory (MB)';

    UPDATE @Out 
    SET ItemValue = 'Low PLE indicates Max Server Memory should be adjusted upwards.'
    WHERE ItemDesc = N'Recommended Max Memory Reason';

    UPDATE @Out 
    SET ItemValue = 3
    WHERE ItemDesc = N'Recommended Max Memory Signal';
END

IF (@MaxServerMemory + @AdditionalMemory >= 1024) AND (@PLESeconds > @MinPLE)
BEGIN
    UPDATE @Out 
    SET ItemValue = 
        (SELECT TOP(1) Inc
        FROM (
            SELECT Inc = t.RowNum * 256
            FROM (
                SELECT RowNum = CONVERT(BIGINT,ROW_NUMBER() OVER (ORDER BY o.object_id))
                FROM sys.objects o, sys.objects o1
                ) t
            WHERE (t.RowNum * 256) <  CONVERT(BIGINT,POWER(2,30))
            ) t1
        WHERE t1.Inc <= CONVERT(INT, (@MaxServerMemory * @PLEMultiplier))
        ORDER BY t1.Inc DESC)
    WHERE ItemDesc = N'Recommended Max Memory (MB)';

    UPDATE @Out 
    SET ItemValue = 'High PLE indicates Max Server Memory could be adjusted downwards.'
    WHERE ItemDesc = N'Recommended Max Memory Reason';

    UPDATE @Out 
    SET ItemValue = 4
    WHERE ItemDesc = N'Recommended Max Memory Signal';
END

DECLARE @RecommendedMaxServerMemory INT;
SELECT  @RecommendedMaxServerMemory = CONVERT(INT,ItemValue)
FROM @Out o 
WHERE o.ItemDesc = N'Recommended Max Memory (MB)';

IF @RecommendedMaxServerMemory > (@MaxServerMemory * 0.96)
    AND @RecommendedMaxServerMemory < (@MaxServerMemory * 1.04)
BEGIN
    UPDATE @Out
    SET ItemValue = @MaxServerMemory
    WHERE ItemDesc = N'Recommended Max Memory (MB)';
    UPDATE @Out
    SET ItemValue = 'No changed recommended'
    WHERE ItemDesc = N'Recommended Max Memory Reason';
    UPDATE @Out 
    SET ItemValue = 0
    WHERE ItemDesc = N'Recommended Max Memory Signal';
END 

IF (@HTMLOutput = 1)
BEGIN
    SELECT ItemValue
        , HTMLOutput = '<table>' + 
            (
                SELECT 'td' = ItemDesc
                    , ''
                    , 'td' = ItemValue
                    , ''
                FROM @Out o
                WHERE CASE WHEN @Debug = 0 THEN o.IsDebug ELSE 0 END = 0
                ORDER BY o.KeyID
                FOR XML PATH('tr')
            ) +
            '</table>'
    FROM @Out o
    WHERE o.ItemDesc = N'Recommended Max Memory Signal';
END
ELSE
BEGIN
    SELECT *
    FROM @Out o
    WHERE CASE WHEN @Debug = 0 THEN o.IsDebug ELSE 0 END = 0
    ORDER BY o.KeyID;
END

Bu kod, PLE'yi max server memorysistemin yapılandırdığı miktar için minimum "kabul edilebilir" PLE ile karşılaştırır . PLE kabul edilebilir sayıdan oldukça yüksekse, maksimum% 10 daha düşük olduğunu gösterir max server memory. PLE kabul edilebilir PLE'den düşükse, maksimum% 10 daha fazla önerir max server memory.

Gerçekleştirilen arabellek havuzu miktarının hedef arabellek havuzu boyutundan az olması durumunda, max server memorybu miktarın düşürülmesini , ayrıca iş parçacığı, tembel yazma vb.

Kod ayrıca Tembel Yazma / saniye, Ücretsiz Liste Durakları ve Toplu İstekler gibi işlemler için çeşitli performans sayaçlarına bakar.

Kod mükemmel değil, giriş yapmak ve gelecekteki SO kullanıcılarının yararı için burada paylaşıyorum.


1
SQL Server 2012 Arabellek Havuzu hedefinden başlayarak ve işlediğiniz Max Mind'in hiçbir anlamı yoktur ve bu sayaçlar kullanımdan kaldırılmıştır. Bunun yerine, Bellek Yöneticisi Hedef Taahhüdünü (KB) ve geçerli işlemi kullanmalısınız. Daha fazla okumak istiyorsanız neden yanlış değer veriyor sosyal.technet.microsoft.com/wiki/contents/articles/…
Shanky
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.