วิธีการกำหนดค่าสำหรับการประเมินขนาดบัฟเฟอร์พูลที่เหมาะสมคืออะไร?


29

ฉันกำลังพยายามหาวิธีที่ชาญฉลาดเพื่อทำความเข้าใจว่าการmax server memory (mb)ตั้งค่านั้นเหมาะสมหรือไม่ (ควรจะต่ำกว่าหรือสูงกว่าหรืออยู่ในแนวทางที่เหมาะสม) ฉันรู้ว่าmax server memory (mb)ควรจะต่ำพอที่จะออกจากห้องสำหรับระบบปฏิบัติการตัวเอง ฯลฯ

สภาพแวดล้อมที่ฉันกำลังมองหามีเซิร์ฟเวอร์หลายร้อยเครื่อง ฉันต้องการสูตรที่เชื่อถือได้ฉันสามารถใช้เพื่อตรวจสอบว่าขนาดปัจจุบันของบัฟเฟอร์พูลนั้นเหมาะสมหรือไม่เนื่องจาก RAM คิดต้นทุนต่อ GB ที่จัดสรรให้กับเซิร์ฟเวอร์แต่ละเครื่อง สภาพแวดล้อมทั้งหมดถูกจำลองเสมือนและ RAM "ทางกายภาพ" ที่จัดสรรให้กับ VM สามารถเปลี่ยนแปลงได้ง่ายขึ้นหรือลง

ฉันมีอินสแตนซ์ของเซิร์ฟเวอร์ SQL ที่เฉพาะเจาะจงฉันกำลังดูด้วย PLE ที่ 1,100,052 วินาทีซึ่งเท่ากับ 12.7 วัน (ระยะเวลาที่เซิร์ฟเวอร์ใช้งาน) เซิร์ฟเวอร์มีการตั้งค่าหน่วยความจำสูงสุดของเซิร์ฟเวอร์ที่ 2560MB (2.5GB) ซึ่งมีการกำหนดเพียง 1380MB (1.3GB) เท่านั้น

ฉันได้อ่านหลายรายการรวมถึงหนึ่งโดย Jonathan Keheyias ( โพสต์ ) และอีกรายการโดย Paul Randal ( โพสต์ ) และอีกหลายรายการ โจนาธานสนับสนุนให้ตรวจสอบ PLE ต่ำกว่า 300 ต่อบัฟเฟอร์พูล4GB ที่ต่ำเกินไป สำหรับอินสแตนซ์ของเซิร์ฟเวอร์ SQL ด้านบน300 * (2.5 / 4) = 187ผลลัพธ์ในเป้าหมาย PLE ต่ำจริง ๆ ต่ำกว่า 300 ตัวอย่างนี้มีข้อมูล SQL Server 290GB (ไม่รวมไฟล์บันทึก) และใช้สำหรับการทดสอบการรวมระบบเท่านั้น สมมติว่า 12 วันที่ผ่านมาเป็นตัวแทนของการใช้งานทั่วไปสำหรับเซิร์ฟเวอร์นี้ฉันจะบอกว่าการmax server memory (mb)ตั้งค่าอาจลดลง

ที่ปลายอีกด้านของเครื่องชั่งฉันมีเซิร์ฟเวอร์ทดสอบรวมอีกตัวหนึ่งที่มี PLE เท่ากับ 294 ซึ่งมีการmax server memory (mb)ตั้งค่าเพียง 1GB เซิร์ฟเวอร์นี้มีข้อมูล SQL Server เพียง 224MB เท่านั้นซึ่งไม่รวมถึงบันทึกและกำลังเรียกใช้ฐานข้อมูล BizFlow บางส่วน เซิร์ฟเวอร์นี้อาจได้รับประโยชน์จากการmax server memory (mb)ตั้งค่าที่สูงขึ้น

ฉันคิดว่าสถานที่เริ่มต้นที่ดีสำหรับเป้าหมายที่อาจได้รับมอบหมายหน่วยความจำมากเกินไปอาจรวมถึงการดูที่:

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;

ถ้าBufferPoolCommitTargetMB / BufferPoolCommittedMBมากกว่า 1 แสดงว่าเซิร์ฟเวอร์ไม่ได้ใช้พูลบัฟเฟอร์ทั้งหมด ถ้าเครื่องที่มีปัญหานอกจากนี้ยังมีของ PLE มากกว่า "x" max server memory (mb)แล้วมันอาจจะเป็นผู้สมัครที่ดีสำหรับการลดลงของ

ตั้งแต่ Buffer Manager:Lazy writes/secนับประสิทธิภาพจะติดตามจำนวนครั้งที่ SQLOS เขียนเพจออกไปยังดิสก์ระหว่างจุดตรวจสอบเนื่องจากความดันหน่วยความจำนี่อาจเป็นอีกสิ่งที่ควรพิจารณา

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;

โค้ดด้านบนถือว่าเซิร์ฟเวอร์อยู่ระหว่างการโหลดในช่วง 15 วินาทีที่ใช้ในการรันมิฉะนั้นจะรายงาน 0; ซึ่งอาจเป็นเท็จลบที่ทำให้เข้าใจผิด

ฉันควรจะดูด้วย PAGELATCHIO_*สถิติการรอหรือประเภทการรออื่น ๆ เป็นตัวบ่งชี้ความดันหน่วยความจำหรือไม่

คำถามของฉันคือฉันจะกำหนดมูลค่าเป้าหมายที่ดีสำหรับ PLE และเชื่อถือได้max server memory (mb)อย่างไร

คำตอบ:


11

ดังที่คุณทราบอยู่แล้วว่าไม่มีสูตรทั่วไปในการคำนวณหน่วยความจำเซิร์ฟเวอร์สูงสุดคุณสามารถทำการคำนวณทางคณิตศาสตร์และเข้าถึงค่าได้ แต่คุณยังต้องการความช่วยเหลือจากเคาน์เตอร์ Perfmon ในที่สุดเพื่อตรวจสอบการใช้งานหน่วยความจำและการเปลี่ยนแปลง ฉันรู้สูตรทั่วไปด้านล่างและฉันก็ใช้เช่นกัน ฉันเรียนรู้สูตรนี้จากลิงค์นี้

สำหรับ SQL Server 2005 ถึง 2008 R2

โปรดทราบว่าหน่วยความจำเซิร์ฟเวอร์สูงสุดของ SQL Server 2005 ถึง 2008 R2 ควบคุมพูลบัฟเฟอร์เท่านั้น ดังนั้นการกำหนดค่าหน่วยความจำเซิร์ฟเวอร์สูงสุดค่อนข้างน่าเบื่อที่นี่และมีการคำนวณน้อย

  1. ทิ้งหน่วยความจำ 2 G ทันทีสำหรับระบบปฏิบัติการ Windows

  2. แน่นอนว่าระบบจะมีโปรแกรมป้องกันไวรัสทำงานอยู่ โปรดออก 1.5G สำหรับ Antivirus โปรดทราบว่า Mcafee และ SQL Server ไม่ได้ไปด้วยกันดังนั้นให้แน่ใจว่าคุณปล่อยให้เพียงพอ คุณยังสามารถตรวจสอบตัวนับ perfmon Perfmon Process-> Private bytes and Working Setเพื่อตรวจสอบการใช้งานหน่วยความจำด้วย AV และแอปพลิเคชันขนาดเล็กอื่น ๆ ที่ทำงานบน SQL Server

ป้อนคำอธิบายรูปภาพที่นี่

  1. พิจารณาความต้องการของหน่วยความจำของไดรเวอร์ / เฟิร์มแวร์คุณจะต้องได้รับมันตามความต้องการของหน่วยความจำโดยไดรเวอร์ที่ติดตั้งในระบบ เครื่องมือ RAMMAP สามารถช่วยได้

  2. พิจารณาข้อกำหนดของหน่วยความจำ NonbPool (aka MTL หรือ MTR) โดย SQL Server

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

    +ผู้ทำงานสูงสุด * 2MB

    +หน่วยความจำสำหรับการจัดสรร Windows โดยตรงประมาณ 0 ถึง 300 MB ในกรณีส่วนใหญ่ แต่คุณอาจต้องเพิ่มถ้ามีองค์ประกอบของบุคคลที่ 3 จำนวนมากที่โหลดในกระบวนการ SQL Server (รวมถึง dll เซิร์ฟเวอร์ที่เชื่อมโยง, dll ตัวสำรองของบุคคลที่สามเป็นต้น)

    +ถ้าคุณใช้ CLR อย่างกว้างขวางเพิ่มหน่วยความจำเพิ่มเติมสำหรับ CLR

  3. พิจารณาความต้องการของหน่วยความจำตามงาน (รวมถึงตัวแทนการจำลองแบบ, บันทึกการจัดส่ง ฯลฯ ) และแพ็คเกจที่จะทำงานบนเซิร์ฟเวอร์ สามารถทำได้ตั้งแต่ MB ถึง GB ตามจำนวนงานที่เปิดอยู่ สำหรับเซิร์ฟเวอร์ขนาดกลางคุณสามารถรับได้ 250 MB

  4. ตรวจสอบให้แน่ใจว่ามีพื้นที่ว่างเพียงพอสำหรับระบบปฏิบัติการ

    ประมาณ (100 MB สำหรับแต่ละ GB จนถึง 4G) + (50 MB สำหรับแต่ละ GB จนถึง 12GB เพิ่มเติม) + (25 MB สำหรับ GB เพิ่มเติมแต่ละจนกว่าขนาด RAM ของคุณ)

  5. ข้อกำหนดหน่วยความจำอื่น ๆ

    หากคุณมีข้อกำหนดหน่วยความจำอื่น ๆ ที่เฉพาะเจาะจงกับสภาพแวดล้อมของคุณ

    หน่วยความจำเซิร์ฟเวอร์สูงสุด = หน่วยความจำกายภาพทั้งหมด - (1 + 2 + 3 + 4 + 5 + 6 + 7)

    ฉันไม่ได้รวมการกำหนดค่าหน่วยความจำสำหรับ SSIS.SSRS, SSAS คุณจะต้องลบหน่วยความจำที่บริการเหล่านี้ต้องการจากหน่วยความจำฟิสิคัลเซิร์ฟเวอร์ทั้งหมด

    หลังจากที่คุณได้กำหนดค่าข้างต้นคุณจำเป็นต้องตรวจสอบเคาน์เตอร์ดังต่อไปนี้

  • SQLServer: ตัวจัดการบัฟเฟอร์ - Page Life Expectancy (PLE):

  • SQLServer: ตัวจัดการบัฟเฟอร์ - CheckpointPages / วินาที:

  • SQLServer: ตัวจัดการหน่วยความจำ - หน่วยความจำที่ค้างอยู่:

  • SQLServer: ตัวจัดการหน่วยความจำ - หน่วยความจำเซิร์ฟเวอร์เป้าหมาย:

  • SQLServer: memory manager - หน่วยความจำเซิร์ฟเวอร์ทั้งหมด

สำหรับ SQL Server 2012/2014

From SQL Server 2012 onwardsการตั้งค่าหน่วยความจำเซิร์ฟเวอร์สูงสุดกลายเป็นเรื่องง่าย เพราะตอนนี้หน่วยความจำเซิร์ฟเวอร์สูงสุดเกือบบัญชีสำหรับปริมาณการใช้หน่วยความจำทั้งหมด หน่วยความจำเซิร์ฟเวอร์สูงสุดควบคุมการจัดสรรหน่วยความจำของ SQL Server รวมถึงบัฟเฟอร์พูลหน่วยความจำคอมไพล์แคชทั้งหมดหน่วยความจำ qe หน่วยความจำตัวจัดการล็อกและหน่วยความจำ CLR (โดยทั่วไปคือ "เสมียน" ใด ๆ ที่พบใน dm_os_memory_clerks) หน่วยความจำสำหรับเธรดกองซ้อนผู้ให้บริการเซิร์ฟเวอร์ที่เชื่อมโยงอื่นนอกเหนือจาก SQL Server หรือหน่วยความจำใด ๆ ที่จัดสรรโดย“ ไม่ใช่ SQL Server” DLL จะไม่ถูกควบคุมโดยหน่วยความจำเซิร์ฟเวอร์สูงสุด

คุณสามารถจัดสรร 75-80% ให้กับ SQL Server จากนั้นใช้เคาน์เตอร์ perfmon เพื่อตรวจสอบการใช้หน่วยความจำ ใน SQL Server 2012 ตัวนับจำนวนเต็ม perfmon ได้รับการคัดค้าน ตัวจัดการบัฟเฟอร์ตัวนับเลิกใช้แล้วคุณต้องใช้ตัวจัดการตัวนับหน่วยความจำ

  • SQL Server: ตัวจัดการหน่วยความจำ - หน่วยความจำเซิร์ฟเวอร์เป้าหมาย (KB)

  • SQL Server: ตัวจัดการหน่วยความจำ - หน่วยความจำเซิร์ฟเวอร์ทั้งหมด (KB)

  • SQL Server: หน่วยความจำตัวจัดการหน่วยความจำฟรี (KB)

  • SQL Server: ตัวจัดการหน่วยความจำ - ฐานข้อมูลแคชหน่วยความจำ (KB)

ตามมูลค่าของ PLE ฉันได้ใช้สูตรโดย Joanthan และโชคดีที่มันได้ผลสำหรับฉัน


6

ความท้าทายที่นี่คือตัวเลขไม่ได้คำนึงถึงประสบการณ์ของผู้ใช้ปลายทาง

ตัวอย่างที่ดี: ฉันมีเซิร์ฟเวอร์ฐานข้อมูลที่ใช้ในการติดตามทุกเว็บไซต์ที่พนักงานของ บริษัท เยี่ยมชม ฉันไม่สนใจว่าจะไม่สามารถติดตามเม็ดมีดได้ขณะโหลดสูงสุดเนื่องจากแอปส่วนหน้าแบตช์แทรกเป็นระยะและเม็ดมีดช้าไม่ทำให้เกิดปัญหากับผู้ใช้ ผู้ใช้ยังคงสามารถท่องเว็บได้โดยไม่ต้องถูกแทรกโดยการแทรกช้า

ในช่วงเวลาที่เลือกแผนกทรัพยากรบุคคลเพิ่งปิดรายงานเมื่อถูกถามถึงประวัติการเรียกดูที่น่าสงสัยสำหรับพนักงานที่ได้รับ แต่พวกเขาไม่สนใจว่าจะใช้เวลานานแค่ไหนในการรายงานพวกเขาเพิ่งเปิดรายงานและออกไปทำสิ่งอื่น ๆ

ประสิทธิภาพต้องเริ่มจากคำถาม: ผู้ใช้พอใจกับประสิทธิภาพหรือไม่ ถ้าเป็นเช่นนั้นปล่อยให้ระบบอยู่ในตำแหน่งเดิม


แม้ว่าคุณจะใช้หน่วยความจำมากกว่าที่คุณต้องการ?
James Anderson

2
James - โดยทั่วไปแล้วฉันไม่ต้องการเปลี่ยนแปลงที่ทำให้ผู้ใช้บ่น หากคุณต้องการทำเช่นนั้นคุณสามารถค่อยๆลดจำนวนหน่วยความจำสำหรับแต่ละเซิร์ฟเวอร์จนกว่าผู้ใช้จะเริ่มบ่น แต่เมื่อฉันทำงานหนักเกินไปฉันมักจะไม่มีเวลาทำตามขั้นตอนเหล่านั้น ฉันต้องมุ่งเน้นไปที่งานที่จะทำให้ผู้ใช้ที่ไม่มีความสุขมีความสุข - แทนที่จะพยายามทำให้ผู้ใช้ที่มีความสุขไม่พอใจ ;-)
Brent Ozar

2
จุดดีเบรนต์ ฉันถูกขอให้ดูว่าเซิร์ฟเวอร์บางตัวมีการจัดสรรมากเกินไปหรือไม่เพราะเราจ่ายหน่วยความจำต่อ GB ต่อปี หลายครั้งที่ฉันดูมีสิ่งที่ฉันคิดว่าเป็น RAM ในปริมาณที่น้อยมากmax server memory (mb)และดังนั้นฉันจึงค่อนข้างลังเลที่จะปรับขนาดให้เล็กลง อย่างไรก็ตามอินสแตนซ์อื่น ๆ มี 1,000,000 + PLE และดังนั้นจึงเป็นตัวเลือกที่เหมาะสมสำหรับการปล่อยแรม เห็นได้ชัดว่าการลด RAM จะทำให้เกิดการเพิ่มขึ้นของ IOPS และผมไม่แน่ใจว่าสิ่งที่ค่าใช้จ่ายของที่จะ
Max Vernon

1
นอกจากนี้การดู PLE เมื่อเทียบกับmax server memoryฉากก็เป็นเรื่องไก่และไข่ การmax server memoryตั้งค่าที่ต่ำกว่า PLE "ยอมรับ" ต่ำสุดจะต่ำกว่าดังนั้นฉันจึงสามารถติดอยู่ในเกลียวที่ลดลงได้ ฉันแน่ใจว่าอย่างที่คุณพูดถึงประสิทธิภาพของผู้ใช้ในบางครั้งจะได้รับผลกระทบ
Max Vernon

ตัวนับ PLE เป็นสิ่งที่คุณควรหลีกเลี่ยงตั้งแต่ 2012 เป็นต้นไปหรือเมื่อคุณมีระบบ NUMA ที่แต่ละโหนดทำงานเป็นตัวจัดสรรหน่วยความจำขนาดเล็กของตัวเอง ถ้าคุณต้องการคุณควรมองหา PLE สำหรับแต่ละโหนด NUMA ไม่สมบูรณ์คุณอาจได้รับค่าไม่ถูกต้อง
Shanky

3

T-SQL ปัจจุบันที่ฉันใช้เพื่อประเมิน PLE vs 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

รหัสนี้เปรียบเทียบ PLE กับ PLE "ยอมรับ" ต่ำสุดสำหรับจำนวนของmax server memoryระบบที่กำหนดค่าไว้ ถ้าเป็น PLE ประเมินสูงกว่าจำนวนที่ยอมรับได้ก็แสดงให้เห็นสูงสุด 10% max server memoryที่ต่ำกว่า หาก PLE ต่ำกว่า PLE ยอมรับมันแสดงให้เห็นสูงสุด 10% max server memoryขึ้น

หากจำนวนพูลบัฟเฟอร์ที่กำหนดไว้จริงน้อยกว่าขนาดบัฟเฟอร์พูลเป้าหมายแนะนำให้ลดmax server memoryจำนวนนั้นรวมทั้งหน่วยความจำเพิ่มเติมสำหรับเธรดการเขียนขี้เกียจ ฯลฯ

โค้ดยังดูที่เคาน์เตอร์วัดประสิทธิภาพต่างๆสำหรับสิ่งต่างๆเช่น Lazy Writes / วินาทีแผงรายการอิสระและคำขอแบทช์

รหัสไม่สมบูรณ์ฉันแบ่งปันที่นี่เพื่อรับข้อมูลและเพื่อประโยชน์ของผู้ใช้ SO ในอนาคต


1
Max Mind ที่คุณเริ่มต้นจากเป้าหมายบัฟเฟอร์พูลของ SQL Server 2012 และไม่ยอมรับและตัวนับเหล่านี้จะถูกคัดค้าน แต่คุณต้องใช้ Memory Manager Target Committed (KB) และการยืนยันปัจจุบัน หากคุณต้องการอ่านเพิ่มเติมว่าทำไมมันจึงให้คุณค่าที่ไม่ถูกต้องsocial.technet.microsoft.com/wiki/contents/articles/ …
Shanky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.