Phương pháp xác định để đánh giá kích thước vùng đệm hợp lý là gì?


29

Tôi đang cố gắng đưa ra một cách lành mạnh để hiểu liệu max server memory (mb)cài đặt có phù hợp hay không (nên thấp hơn hoặc cao hơn hoặc giữ nguyên như vậy). Tôi nhận thấy rằng max server memory (mb)phải luôn đủ thấp để chừa chỗ cho hệ điều hành, v.v.

Môi trường tôi đang xem có hàng trăm máy chủ; Tôi cần một công thức đáng tin cậy mà tôi có thể sử dụng để xác định xem kích thước hiện tại của vùng đệm có phù hợp hay không vì RAM được tính cho mỗi GB được phân bổ cho mỗi máy chủ. Toàn bộ môi trường được ảo hóa và RAM "vật lý" được phân bổ cho VM có thể dễ dàng thay đổi lên hoặc xuống.

Tôi có một Trường hợp Máy chủ SQL cụ thể mà tôi đang xem xét với PLE là 1.100.052 giây, tương đương với 12,7 ngày (lượng thời gian máy chủ đã hoạt động). Máy chủ có cài đặt bộ nhớ máy chủ tối đa 2560MB (2,5 GB), trong đó chỉ có 1380 MB (1,3 GB) thực sự được cam kết.

Tôi đã đọc một số mục trong đó có một của Jonathan Keheyias ( bài ) và một mục khác của Paul Randal ( bài ) và một số mục khác. Jonathan ủng hộ việc theo dõi cho PLE dưới 300 trên 4GB vùng đệm là quá thấp. Đối với Trường hợp Máy chủ SQL ở trên, 300 * (2.5 / 4) = 187kết quả PLE mục tiêu thực sự rất thấp dưới 300. Trường hợp này có 290GB dữ liệu Máy chủ SQL (không bao gồm các tệp nhật ký) và chỉ được sử dụng để kiểm tra tích hợp. Giả sử 12 ngày qua là đại diện cho việc sử dụng thông thường cho máy chủ này, tôi muốn nói rằng max server memory (mb)cài đặt có thể được hạ xuống.

Ở đầu kia của thang đo, tôi có một máy chủ thử nghiệm tích hợp khác với PLE là 294, có max server memory (mb)cài đặt chỉ 1GB. Máy chủ này chỉ có 224 MB dữ liệu Máy chủ SQL không bao gồm nhật ký và đang chạy một số cơ sở dữ liệu BizFlow. Máy chủ này có thể được hưởng lợi từ max server memory (mb)cài đặt cao hơn .

Tôi đang nghĩ một nơi khởi đầu tốt cho các mục tiêu có thể được chỉ định quá nhiều bộ nhớ có thể bao gồm việc xem xét:

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;

Nếu BufferPoolCommitTargetMB / BufferPoolCommittedMBlớn hơn 1, máy chủ không sử dụng toàn bộ vùng đệm. Nếu máy đang được đề cập cũng có PLE lớn hơn "x" thì đó có thể là một ứng cử viên tốt để giảm giá max server memory (mb).

Vì bộ Buffer Manager:Lazy writes/secđếm hiệu suất theo dõi số lần SQLOS đã ghi các trang ra đĩa giữa các điểm kiểm tra do áp lực bộ nhớ, đây có thể là một điều tốt để xem xét.

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;

Đoạn mã trên giả định rằng máy chủ đang tải trong 15 giây để chạy, nếu không nó sẽ báo cáo 0; đó có thể là một sai lệch âm tính.

Tôi cũng nên xem các PAGELATCHIO_*số liệu thống kê chờ hoặc một số loại chờ khác như một chỉ báo về áp lực bộ nhớ, hoặc thiếu chúng?

Câu hỏi của tôi là, làm thế nào tôi có thể xác định một cách đáng tin cậy một giá trị mục tiêu "tốt" cho PLE và max server memory (mb)?

Câu trả lời:


11

Như bạn đã biết Không có công thức chung để tính toán bộ nhớ máy chủ tối đa, bạn có thể thực hiện một số phép toán nhanh và đạt đến một giá trị nhưng cuối cùng bạn vẫn cần sự trợ giúp của bộ đếm Perfmon để theo dõi việc sử dụng bộ nhớ và thay đổi tương ứng. Tôi biết dưới đây công thức chung và tôi cũng sử dụng nó. Tôi đã học được công thức này từ Liên kết này

Đối với SQL Server 2005 đến 2008 R2

Xin lưu ý từ bộ nhớ máy chủ tối đa SQL Server 2005 đến 2008 R2 chỉ điều khiển nhóm bộ đệm. Vì vậy, cấu hình bộ nhớ máy chủ tối đa hơi tẻ nhạt ở đây và liên quan đến một vài tính toán

  1. Để lại bộ nhớ 2 G ngay lập tức cho HĐH Windows.

  2. Tất nhiên hệ thống sẽ có chương trình diệt virus. Vui lòng để lại 1.5G cho Antivirus. Xin lưu ý Mcafee và SQL Server không song hành với nhau vì vậy hãy đảm bảo bạn để lại đủ cho nó. Bạn cũng có thể kiểm tra bộ đếm perfmon Perfmon Process-> Private bytes and Working Setđể theo dõi việc sử dụng bộ nhớ bằng AV và các ứng dụng nhỏ khác đang chạy trên hộp SQL Server

nhập mô tả hình ảnh ở đây

  1. Xem xét các yêu cầu bộ nhớ của trình điều khiển / phần cứng. Bạn phải lấy nó dựa trên yêu cầu bộ nhớ của trình điều khiển được cài đặt trên hệ thống. Công cụ RAMMAP có thể giúp

  2. Xem xét các yêu cầu bộ nhớ NonbPool (còn gọi là MTL hoặc MTR) của SQL Server.

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

    + Chủ đề công nhân tối đa * 2MB

    + Bộ nhớ cho phân bổ Windows trực tiếp khoảng 0 đến 300 MB trong hầu hết các trường hợp nhưng bạn có thể phải tăng nó nếu có nhiều thành phần 3 bên được tải trong quy trình SQL Server (Bao gồm dll của máy chủ được liên kết, dll của bên thứ 3, v.v.)

    + Nếu bạn đang sử dụng CLR, hãy thêm một số bộ nhớ bổ sung cho CLR.

  3. Xem xét yêu cầu bộ nhớ theo công việc (Bao gồm các tác nhân sao chép, Vận chuyển nhật ký, v.v.) và các gói sẽ chạy trên máy chủ. Nó có thể rất từ ​​MB đến GB theo số lượng công việc đang chạy. Đối với máy chủ cỡ trung bình, bạn có thể sử dụng 250 MB

  4. Đảm bảo có đủ không gian trống cho hệ điều hành.

    Khoảng (100 MB cho mỗi GB cho đến 4G) + (50 MB cho mỗi GB bổ sung cho đến 12 GB) + (25 MB cho mỗi GB bổ sung cho đến kích thước RAM của bạn)

  5. Yêu cầu bộ nhớ khác.

    Nếu bạn có bất kỳ yêu cầu bộ nhớ khác cụ thể cho môi trường của bạn.

    Bộ nhớ máy chủ tối đa = Tổng bộ nhớ vật lý - (1 + 2 + 3 + 4 + 5 + 6 + 7)

    Tôi chưa bao gồm cấu hình bộ nhớ cho SSIS.SSRS, SSAS, bạn cũng sẽ cần phải trừ bộ nhớ theo yêu cầu của các dịch vụ này khỏi tổng bộ nhớ máy chủ vật lý.

    Sau khi bạn đã cấu hình ở trên, bạn cần theo dõi các bộ đếm sau

  • SQLServer: Trình quản lý bộ đệm - Tuổi thọ trang (PLE):

  • SQLServer: Trình quản lý bộ đệm - CheckpointPages / giây:

  • SQLServer: Trình quản lý bộ nhớ - Cấp phát bộ nhớ đang chờ xử lý:

  • SQLServer: Trình quản lý bộ nhớ - Bộ nhớ máy chủ đích:

  • SQLServer: Trình quản lý bộ nhớ - Tổng bộ nhớ Máy chủ

Đối với máy chủ SQL 2012/2014.

From SQL Server 2012 onwardsthiết lập bộ nhớ máy chủ tối đa đã trở nên dễ dàng. Bởi vì bây giờ bộ nhớ máy chủ tối đa gần như chiếm tất cả mức tiêu thụ bộ nhớ. Bộ nhớ máy chủ tối đa kiểm soát cấp phát bộ nhớ Máy chủ SQL, bao gồm nhóm bộ đệm, bộ nhớ biên dịch, tất cả bộ nhớ cache, cấp bộ nhớ qe, bộ nhớ quản lý khóa và bộ nhớ CLR (về cơ bản là bất kỳ clerk nào được tìm thấy trong dm_os_memory_clerks). Bộ nhớ cho ngăn xếp luồng, heaps, nhà cung cấp máy chủ được liên kết khác với SQL Server hoặc bất kỳ bộ nhớ nào được cấp phát bởi một máy chủ không phải là SQL Server DLL DLL không được kiểm soát bởi bộ nhớ máy chủ tối đa.

Bạn có thể phân bổ 75-80% cho SQL Server và sau đó sử dụng bộ đếm perfmon để theo dõi việc sử dụng bộ nhớ. Trong SQL Server 2012, một số bộ đếm perfmon đã không được dùng nữa. Bộ đếm trình quản lý bộ đệm không dùng nữa, bạn phải sử dụng bộ đếm trình quản lý bộ nhớ

  • SQL Server: Trình quản lý bộ nhớ-- Bộ nhớ máy chủ mục tiêu (KB)

  • SQL Server: Trình quản lý bộ nhớ - Tổng bộ nhớ máy chủ (KB)

  • SQL Server: Trình quản lý bộ nhớ- Bộ nhớ trống (KB)

  • SQL Server: Trình quản lý bộ nhớ - Bộ nhớ cache cơ sở dữ liệu (KB)

Về giá trị của PLE, tôi đã sử dụng công thức của Joanthan và may mắn thay, nó đã làm việc cho tôi.


6

Thách thức ở đây là những con số không tính đến trải nghiệm người dùng cuối.

Ví dụ tuyệt vời: Tôi có máy chủ cơ sở dữ liệu được sử dụng để theo dõi mọi trang web mà nhân viên công ty truy cập. Tôi không quan tâm nếu nó không theo kịp các phần chèn trong khi tải cao điểm vì ứng dụng giao diện người dùng sẽ loại bỏ các phần chèn theo định kỳ và các phần chèn chậm không gây ra sự cố cho người dùng. Người dùng vẫn có thể lướt web mà không bị giữ bởi các chèn chậm.

Tại thời điểm CHỌN, bộ phận nhân sự chỉ tắt các báo cáo khi được hỏi về lịch sử duyệt web đáng ngờ cho một nhân viên nhất định, nhưng họ không quan tâm các báo cáo mất bao lâu - họ chỉ mở báo cáo và tắt để làm những việc khác.

Hiệu suất cần bắt đầu bằng một câu hỏi: người dùng có hài lòng với hiệu suất không? Nếu vậy, hãy rời khỏi hệ thống.


Ngay cả khi bạn đang sử dụng nhiều bộ nhớ hơn bạn cần?
James Anderson

2
James - nói chung, tôi không muốn thực hiện các thay đổi khiến người dùng phàn nàn. Nếu bạn muốn làm điều đó, bạn có thể giảm dần dung lượng bộ nhớ cho mỗi máy chủ cho đến khi người dùng bắt đầu phàn nàn, nhưng khi tôi đã làm việc quá sức, tôi thường không có thời gian để thực hiện các bước đó. Tôi phải tập trung vào các nhiệm vụ sẽ làm cho người dùng không hài lòng hạnh phúc - thay vì cố gắng làm cho người dùng hạnh phúc không hài lòng. ;-)
Brent Ozar

2
Điểm tốt, Brent. Tôi được yêu cầu xem liệu một số máy chủ được cung cấp quá mức vì chúng tôi trả tiền cho bộ nhớ mỗi GB mỗi năm. Nhiều trường hợp tôi đang xem có những gì tôi coi là một lượng RAM rất nhỏ max server memory (mb)và do đó tôi khá miễn cưỡng khi giảm kích thước của chúng. Tuy nhiên, một số trường hợp khác có 1.000.000 + PLE và như vậy là những ứng cử viên tiềm năng khá rõ ràng cho việc giảm RAM. Rõ ràng, việc giảm RAM sẽ gây ra sự gia tăng IOps và tôi không chắc chi phí của việc đó sẽ là bao nhiêu.
Max Vernon

1
Ngoài ra, nhìn vào PLE so với các max server memorythiết lập là một loại gà và trứng; càng thấp các max server memorythiết lập, càng thấp ở mức tối thiểu "chấp nhận được" PLE sẽ, vì vậy tôi có thể gặp khó khăn trong một vòng xoáy không ngừng giảm. Tôi chắc chắn, như bạn đã đề cập, hiệu suất của người dùng tại một số điểm sẽ bị ảnh hưởng.
Max Vernon

Bộ đếm PLE là bộ đếm mà bạn nên tránh tìm kiếm từ năm 2012 trở đi hoặc khi bạn có hệ thống NUMA nơi mỗi nút hoạt động như bộ cấp phát bộ nhớ nhỏ của riêng mình. Nếu bạn muốn, bạn nên tìm PLE cho mỗi nút NUMA chưa hoàn thành, bạn có thể nhận được giá trị không chính xác
Shanky

3

T-SQL hiện tại tôi đang sử dụng để đánh giá PLE vs max server memorylà:

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

Mã này so sánh PLE với PLE tối thiểu "chấp nhận được" đối với số lượng max server memoryhệ thống đã được cấu hình. Nếu PLE cao hơn đáng kể so với con số chấp nhận được, nó cho thấy mức tối đa thấp hơn 10% max server memory. Nếu PLE thấp hơn PLE chấp nhận được, nó gợi ý tối đa thêm 10% max server memory.

Nếu số lượng nhóm bộ đệm cam kết thực tế nhỏ hơn kích thước nhóm bộ đệm đích, nó gợi ý giảm xuống mức max server memoryđó, cộng với một số bộ nhớ bổ sung cho các luồng, lười viết, v.v.

Mã này cũng xem xét các bộ đếm hiệu suất khác nhau cho những thứ như Lazy Writes / giây, Free List Stalls và Batch Request.

Mã này không hoàn hảo, tôi chia sẻ nó ở đây để nhận đầu vào và vì lợi ích của người dùng SO trong tương lai.


1
Max Mind bạn bắt đầu từ mục tiêu Bộ đệm SQL Server 2012 và cam kết không có ý nghĩa và các bộ đếm này không được chấp nhận. Thay vào đó, bạn phải sử dụng Mục tiêu của Trình quản lý bộ nhớ (KB) và cam kết hiện tại. Nếu bạn muốn đọc thêm lý do tại sao nó mang lại giá trị sai social.technet.microsoft.com/wiki/contents/articles/...
Shanky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.