From 8efb5538716250ac4c85937714de655e7f035e6f Mon Sep 17 00:00:00 2001 From: Darling Data Date: Tue, 15 Apr 2025 00:27:52 +0000 Subject: [PATCH 1/4] Automation: Format and Build SQL File --- Install-All/DarlingData.sql | 608 +++++++++++++++++++--------------- sp_PerfCheck/sp_PerfCheck.sql | 64 ++-- 2 files changed, 366 insertions(+), 306 deletions(-) diff --git a/Install-All/DarlingData.sql b/Install-All/DarlingData.sql index 21afed15..6ea6c2f8 100644 --- a/Install-All/DarlingData.sql +++ b/Install-All/DarlingData.sql @@ -1,4 +1,4 @@ --- Compile Date: 04/12/2025 17:07:44 UTC +-- Compile Date: 04/15/2025 00:27:51 UTC SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; @@ -21177,6 +21177,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ), 2 ), + @product_level sysname = + CONVERT + ( + sysname, + SERVERPROPERTY(N'ProductLevel') + ), + @product_edition sysname = + CONVERT + ( + sysname, + SERVERPROPERTY(N'Edition') + ), + @server_name sysname = + CONVERT + ( + sysname, + SERVERPROPERTY(N'ServerName') + ), @engine_edition integer = CONVERT ( @@ -21249,8 +21267,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @stolen_memory_gb decimal(38, 2), @stolen_memory_pct decimal(10, 2), @stolen_memory_threshold_pct decimal(10, 2) = 15.0, /* Alert if more than 15% memory is stolen */ - /* Format the output properly without XML PATH which causes spacing issues */ - @wait_summary nvarchar(1000) = N'', /* CPU scheduling variables */ @signal_wait_time_ms bigint, @total_wait_time_ms bigint, @@ -21275,15 +21291,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN TRY EXECUTE sys.sp_executesql N' - DECLARE - @c bigint; - SELECT - @c = 1 + @has_view_server_state = 1 FROM sys.dm_os_sys_info AS osi; - '; - - SET @has_view_server_state = 1; + ', + N'@has_view_server_state bit OUTPUT', + @has_view_server_state OUTPUT; END TRY BEGIN CATCH SET @has_view_server_state = 0; @@ -21534,15 +21547,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. category nvarchar(50) NOT NULL ); - /* Add wait stats summary to server info - focus on uptime impact */ - /* First get top wait categories in a temp table to format properly */ - CREATE TABLE - #wait_summary - ( - category nvarchar(60) NOT NULL, - pct_of_uptime decimal(10, 2) NOT NULL - ); - /* Create temp table for database I/O stalls */ CREATE TABLE #io_stalls_by_db @@ -21572,61 +21576,85 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Basic server information that works across all platforms */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES (N'sp_PerfCheck', N'Brought to you by Darling Data'); INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES (N'https://code.erikdarling.com', N'https://erikdarling.com'); INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES + ( + N'Version', + @version + + N' (' + + CONVERT ( - N'Version', - @version + - N' (' + - CONVERT - ( - varchar(10), - @version_date, - 101 - ) + - N')' - ); + varchar(10), + @version_date, + 101 + ) + + N')' + ); + /* Using server name variable declared earlier */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES - (N'Server Name', CONVERT(sysname, SERVERPROPERTY(N'ServerName'))); + (N'Server Name', @server_name); + /* Using product version and level variables declared earlier */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES - ( - N'SQL Server Version', - CONVERT(sysname, SERVERPROPERTY(N'ProductVersion')) + - N' (' + - CONVERT(sysname, SERVERPROPERTY(N'ProductLevel')) + - N')' - ); + ( + N'SQL Server Version', + @product_version + + N' (' + + @product_level + + N')' + ); + /* Using product edition variable declared earlier */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES - (N'SQL Server Edition', CONVERT(sysname, SERVERPROPERTY(N'Edition'))); + (N'SQL Server Edition', @product_edition); /* Environment information - Already detected earlier */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Environment', CASE @@ -21639,62 +21667,97 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ELSE N'On-premises or IaaS SQL Server' END; - /* Uptime information - works on all platforms */ - INSERT INTO - #server_info - (info_type, value) - SELECT - N'Uptime', - CONVERT + /* Uptime information - works on all platforms if permissions allow */ + IF @has_view_server_state = 1 + BEGIN + INSERT INTO + #server_info ( - nvarchar(30), - DATEDIFF + info_type, + value + ) + SELECT + N'Uptime', + CONVERT ( - DAY, - osi.sqlserver_start_time, - SYSDATETIME() - ) - ) + - N' days, ' + - CONVERT - ( - nvarchar(8), + nvarchar(30), + DATEDIFF + ( + DAY, + osi.sqlserver_start_time, + SYSDATETIME() + ) + ) + + N' days, ' + CONVERT ( - time, - DATEADD + nvarchar(8), + CONVERT ( - SECOND, - DATEDIFF + time, + DATEADD ( SECOND, - osi.sqlserver_start_time, - SYSDATETIME() - ) % 86400, - '00:00:00' - ) - ), - 108 - ) + - N' (hh:mm:ss)' - FROM sys.dm_os_sys_info AS osi; + DATEDIFF + ( + SECOND, + osi.sqlserver_start_time, + SYSDATETIME() + ) % 86400, + '00:00:00' + ) + ), + 108 + ) + + N' (hh:mm:ss)' + FROM sys.dm_os_sys_info AS osi; + END + ELSE + BEGIN + INSERT INTO + #server_info + ( + info_type, + value + ) + VALUES + (N'Uptime', N'Information unavailable (requires VIEW SERVER STATE permission)'); + END; - /* CPU information - works on all platforms */ - INSERT INTO - #server_info - (info_type, value) - SELECT - N'CPU', - CONVERT(nvarchar(10), osi.cpu_count) + - N' logical processors, ' + - CONVERT(nvarchar(10), osi.hyperthread_ratio) + - N' physical cores, ' + - CONVERT(nvarchar(10), ISNULL(osi.numa_node_count, 1)) + - N' NUMA node(s)' - FROM sys.dm_os_sys_info AS osi; + /* CPU information - works on all platforms if permissions allow */ + IF @has_view_server_state = 1 + BEGIN + INSERT INTO + #server_info + ( + info_type, + value + ) + SELECT + N'CPU', + CONVERT(nvarchar(10), osi.cpu_count) + + N' logical processors, ' + + CONVERT(nvarchar(10), osi.hyperthread_ratio) + + N' physical cores, ' + + CONVERT(nvarchar(10), ISNULL(osi.numa_node_count, 1)) + + N' NUMA node(s)' + FROM sys.dm_os_sys_info AS osi; + END + ELSE + BEGIN + INSERT INTO + #server_info + ( + info_type, + value + ) + VALUES + (N'CPU', N'Information unavailable (requires VIEW SERVER STATE permission)'); + END; /* Check for offline schedulers */ IF @azure_sql_db = 0 /* Not applicable to Azure SQL DB */ + AND @has_view_server_state = 1 /* Requires VIEW SERVER STATE permission */ BEGIN INSERT INTO #results @@ -21724,63 +21787,70 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. COUNT_BIG(*) > 0; /* Only if there are offline schedulers */ END; - /* Check for forced grants */ - INSERT INTO - #results - ( - check_id, - priority, - category, - finding, - details, - url - ) - SELECT - check_id = 4101, - priority = 30, /* High priority */ - category = N'Memory Pressure', - finding = N'Memory-Starved Queries Detected', - details = - N'dm_exec_query_resource_semaphores has ' + - CONVERT(nvarchar(10), MAX(ders.forced_grant_count)) + - N' forced memory grants. ' + - N'Queries are being forced to run with less memory than requested, which can cause spills to tempdb and poor performance.', - url = N'https://erikdarling.com/sp_PerfCheck#MemoryStarved' - FROM sys.dm_exec_query_resource_semaphores AS ders - WHERE ders.forced_grant_count > 0 - HAVING - MAX(ders.forced_grant_count) > 0; /* Only if there are actually forced grants */ + /* Check for forced grants - requires VIEW SERVER STATE permission */ + IF @has_view_server_state = 1 + BEGIN + INSERT INTO + #results + ( + check_id, + priority, + category, + finding, + details, + url + ) + SELECT + check_id = 4101, + priority = 30, /* High priority */ + category = N'Memory Pressure', + finding = N'Memory-Starved Queries Detected', + details = + N'dm_exec_query_resource_semaphores has ' + + CONVERT(nvarchar(10), MAX(ders.forced_grant_count)) + + N' forced memory grants. ' + + N'Queries are being forced to run with less memory than requested, which can cause spills to tempdb and poor performance.', + url = N'https://erikdarling.com/sp_PerfCheck#MemoryStarved' + FROM sys.dm_exec_query_resource_semaphores AS ders + WHERE ders.forced_grant_count > 0 + HAVING + MAX(ders.forced_grant_count) > 0; /* Only if there are actually forced grants */ + END; - /* Check for memory grant timeouts */ - INSERT INTO - #results - ( - check_id, - priority, - category, - finding, - details, - url - ) - SELECT - check_id = 4103, - priority = 30, /* High priority */ - category = N'Memory Pressure', - finding = N'Memory-Starved Queries Detected', - details = - N'dm_exec_query_resource_semaphores has ' + - CONVERT(nvarchar(10), MAX(ders.timeout_error_count)) + - N' memory grant timeouts. ' + - N'Queries are waiting for memory for a long time and giving up.', - url = N'https://erikdarling.com/sp_PerfCheck#MemoryStarved' - FROM sys.dm_exec_query_resource_semaphores AS ders - WHERE ders.timeout_error_count > 0 - HAVING - MAX(ders.timeout_error_count) > 0; /* Only if there are actually forced grants */ + /* Check for memory grant timeouts - requires VIEW SERVER STATE permission */ + IF @has_view_server_state = 1 + BEGIN + INSERT INTO + #results + ( + check_id, + priority, + category, + finding, + details, + url + ) + SELECT + check_id = 4103, + priority = 30, /* High priority */ + category = N'Memory Pressure', + finding = N'Memory-Starved Queries Detected', + details = + N'dm_exec_query_resource_semaphores has ' + + CONVERT(nvarchar(10), MAX(ders.timeout_error_count)) + + N' memory grant timeouts. ' + + N'Queries are waiting for memory for a long time and giving up.', + url = N'https://erikdarling.com/sp_PerfCheck#MemoryStarved' + FROM sys.dm_exec_query_resource_semaphores AS ders + WHERE ders.timeout_error_count > 0 + HAVING + MAX(ders.timeout_error_count) > 0; /* Only if there are actually forced grants */ + END; /* Check for SQL Server memory dumps (on-prem only) */ IF @azure_sql_db = 0 AND @azure_managed_instance = 0 + AND @has_view_server_state = 1 /* Requires sysadmin permission */ BEGIN /* First check if the DMV exists (SQL 2008+) */ IF OBJECT_ID('sys.dm_server_memory_dumps') IS NOT NULL @@ -21963,6 +22033,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. FROM sys.dm_os_sys_info AS osi WHERE osi.sql_memory_model_desc = N'CONVENTIONAL' /* Conventional means not using LPIM */ AND @physical_memory_gb >= 32 /* Only recommend for servers with >=32GB RAM */; + + INSERT + #server_info + ( + info_type, + value + ) + SELECT + N'Memory Model', + osi.sql_memory_model_desc + FROM sys.dm_os_sys_info AS osi; END; /* Check if Instant File Initialization is enabled (on-prem only) */ @@ -21973,7 +22054,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Instant File Initialization', CASE @@ -22019,7 +22103,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Resource Governor', N'Enabled'; @@ -22061,7 +22148,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Resource Governor', N'Disabled'; @@ -22077,6 +22167,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN TRY INSERT INTO #trace_flags + ( + trace_flag, + status, + global, + session + ) EXECUTE sys.sp_executesql N'DBCC TRACESTATUS WITH NO_INFOMSGS'; END TRY @@ -22111,7 +22207,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Global Trace Flags', STUFF @@ -22138,7 +22237,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Memory information - works on all platforms */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) SELECT N'Memory', N'Total: ' + @@ -22162,10 +22264,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. osi.committed_target_kb / 1024.0 / 1024.0 ) ) + - N' GB' + - N', ' + - osi.sql_memory_model_desc + - N' enabled' + N' GB' FROM sys.dm_os_sys_info AS osi; /* Check for important events in default trace (Windows only for now) */ @@ -22523,7 +22622,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES (N'Slow Autogrow Events (7 days)', @autogrow_summary); END; @@ -22852,102 +22954,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AND ws.wait_type <> N'SLEEP_TASK' ORDER BY ws.wait_time_percent_of_uptime DESC; - - INSERT INTO - #wait_summary - (category, pct_of_uptime) - SELECT TOP (5) - ws.category, - pct_of_uptime = - SUM(ws.wait_time_percent_of_uptime) - FROM #wait_stats AS ws - WHERE ws.wait_time_percent_of_uptime >= 10.0 /* Only include categories with at least 10% impact on uptime */ - GROUP BY - ws.category - ORDER BY - SUM(ws.wait_time_percent_of_uptime) DESC; - - SELECT @wait_summary = - CASE - WHEN @wait_summary = N'' - THEN ws.category + - N' (' + - CONVERT(nvarchar(10), ws.pct_of_uptime) + - N'% of uptime)' - ELSE @wait_summary + - N', ' + - ws.category + - N' (' + - CONVERT(nvarchar(10), ws.pct_of_uptime) + - N'% of uptime)' - END - FROM #wait_summary AS ws; - - /* Add wait summary to server info if any significant waits were found */ - IF @wait_summary <> N'' - BEGIN - /* Replace the result set in the server_info table with a clearer explanation */ - INSERT INTO - #server_info - (info_type, value) - VALUES - (N'Wait Stats Summary', N'See Wait Statistics section in results for details.'); - - /* Add the detailed wait categories as separate entries in the results table */ - INSERT INTO - #results - ( - check_id, - priority, - category, - finding, - details, - url - ) - SELECT TOP (10) - 6000, - priority = - CASE - WHEN ws.pct_of_uptime > 100 - THEN 40 /* Medium-high priority */ - WHEN ws.pct_of_uptime > 50 - THEN 50 /* Medium priority */ - ELSE 60 /* Lower priority */ - END, - category = N'Wait Statistics Summary', - finding = N'Wait Category: ' + ws.category, - details = - N'This category represents ' + - CONVERT(nvarchar(10), CONVERT(decimal(10, 2), ws.pct_of_uptime)) + - N'% of server uptime. ' + - CASE - WHEN ws.category = N'Query Execution' - THEN N'This includes various query processing waits and can indicate poorly optimized queries or procedure cache issues.' - WHEN ws.category = N'Parallelism' - THEN N'This indicates time spent coordinating parallel query execution. Consider reviewing MAXDOP settings.' - WHEN ws.category = N'CPU' - THEN N'This indicates CPU pressure. Server may benefit from more CPU resources or query optimization.' - WHEN ws.category = N'Memory' - THEN N'This indicates memory pressure. Consider increasing server memory or optimizing memory-intensive queries.' - WHEN ws.category = N'I/O' - THEN N'This indicates storage performance issues. Check for slow disks or I/O-intensive queries.' - WHEN ws.category = N'TempDB Contention' - THEN N'This indicates contention in TempDB. Consider adding more TempDB files or optimizing queries that use TempDB.' - WHEN ws.category = N'Transaction Log' - THEN N'This indicates log write pressure. Check for long-running transactions or log file performance issues.' - WHEN ws.category = N'Locking' - THEN N'This indicates contention from locks. Look for blocking chains or query isolation level issues.' - WHEN ws.category = N'Network' - THEN N'This indicates network bottlenecks or slow client applications not consuming results quickly.' - WHEN ws.category = N'Azure SQL Throttling' - THEN N'This indicates resource limits imposed by Azure SQL DB. Consider upgrading to a higher service tier.' - ELSE N'This category may require further investigation.' - END, - url = N'https://erikdarling.com/sp_PerfCheck#WaitStats' - FROM #wait_summary AS ws - ORDER BY - ws.pct_of_uptime DESC; - END; END; /* Check for CPU scheduling pressure (signal wait ratio) */ @@ -23039,7 +23045,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Add CPU scheduling info to server_info */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Signal Wait Ratio', @@ -23058,7 +23067,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'SOS_SCHEDULER_YIELD', @@ -23179,7 +23191,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Add buffer pool info to server_info */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Buffer Pool Size', @@ -23193,7 +23208,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Stolen Memory', @@ -23486,7 +23504,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Database I/O Stalls', @@ -23836,7 +23857,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* For non-Azure SQL DB, get size across all accessible databases */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) EXECUTE sys.sp_executesql @db_size_sql; END; @@ -23845,7 +23869,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* If we can't access the files due to permissions */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES (N'Database Size', N'Unable to determine (permission error)'); END CATCH; @@ -23879,7 +23906,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Add min/max server memory info */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Min Server Memory', @@ -23889,7 +23919,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Max Server Memory', @@ -23910,7 +23943,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'MAXDOP', @@ -23919,7 +23955,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES ( N'Cost Threshold for Parallelism', @@ -24218,7 +24257,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'Single TempDB Data File', N'TempDB has only one data file. Multiple files can reduce allocation page contention. ' + N'Recommendation: Use multiple files (equal to number of logical processors up to 8).', - N'https://erikdarling.com/sp_PerfCheck#TempDB' + N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; @@ -24246,7 +24285,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N' data files. This is an odd number and not equal to the ' + CONVERT(nvarchar(10), @processors) + ' logical processors. ' + N'Consider using an even number of files for better performance.', - N'https://erikdarling.com/sp_PerfCheck#TempDB' + N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; @@ -24274,7 +24313,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N' data files, which is more than the ' + CONVERT(nvarchar(10), @processors) + N' logical processors. ', - N'https://erikdarling.com/sp_PerfCheck#TempDB' + N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; @@ -24304,7 +24343,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N' GB, Largest: ' + CONVERT(nvarchar(10), CONVERT(integer, @max_data_file_size)) + N' GB. For best performance, TempDB data files should be the same size.', - N'https://erikdarling.com/sp_PerfCheck#TempDB' + N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; @@ -24330,7 +24369,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'Mixed TempDB Autogrowth Settings', N'TempDB data files have inconsistent autogrowth settings - some use percentage growth and others use fixed size growth. ' + N'This can lead to uneven file sizes over time. Use consistent settings for all files.', - N'https://erikdarling.com/sp_PerfCheck#TempDB' + N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; @@ -24541,7 +24580,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'Affinity I/O mask has been manually configured to ' + CONVERT(nvarchar(20), @affinity_io_mask) + N'. This binds I/O completion to specific CPUs and should only be used for specialized workloads.', - N'https://erikdarling.com/sp_PerfCheck/#AffinityMask' + N'https://erikdarling.com/sp_PerfCheck/#AffinityIOMask' ); END; @@ -24567,7 +24606,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'Affinity64 mask has been manually configured to ' + CONVERT(nvarchar(20), @affinity64_mask) + N'. This can limit SQL Server CPU usage on high-CPU systems and should be carefully evaluated.', - N'https://erikdarling.com/sp_PerfCheck/#AffinityMask' + N'https://erikdarling.com/sp_PerfCheck/#Affinity64Mask' ); END; @@ -24593,7 +24632,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'Affinity64 I/O mask has been manually configured to ' + CONVERT(nvarchar(20), @affinity64_io_mask) + N'. This binds I/O completion on high-CPU systems and should be carefully evaluated.', - N'https://erikdarling.com/sp_PerfCheck/#AffinityMask' + N'https://erikdarling.com/sp_PerfCheck/#Affinity64Mask' ); END; @@ -25839,7 +25878,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Add scan time footer to server info */ INSERT INTO #server_info - (info_type, value) + ( + info_type, + value + ) VALUES (N'Run Date', CONVERT(varchar(25), @start_time, 121)); @@ -27547,8 +27589,12 @@ OPTION(MAXDOP 1, RECOMPILE);', ISNULL ( vfs.io_stall_read_ms / - (NULLIF(vfs.num_of_reads, 0)), - 0 + CONVERT + ( + decimal(38, 2), + NULLIF(vfs.num_of_reads, 0.) + ), + 0. ) ), total_gb_written = @@ -27580,15 +27626,29 @@ OPTION(MAXDOP 1, RECOMPILE);', ISNULL ( vfs.io_stall_write_ms / - (NULLIF(vfs.num_of_writes, 0)), - 0 + CONVERT + ( + decimal(38, 2), + NULLIF(vfs.num_of_writes, 0.) + ), + 0. ) ), io_stall_read_ms, io_stall_write_ms, sample_time = SYSDATETIME() - FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs + FROM sys.dm_io_virtual_file_stats + (' + + CASE + WHEN @azure = 1 + THEN N' + DB_ID()' + ELSE N' + NULL' + END + N', + NULL + ) AS vfs JOIN ' + CONVERT ( diff --git a/sp_PerfCheck/sp_PerfCheck.sql b/sp_PerfCheck/sp_PerfCheck.sql index 8e3747e4..6084d55a 100644 --- a/sp_PerfCheck/sp_PerfCheck.sql +++ b/sp_PerfCheck/sp_PerfCheck.sql @@ -633,8 +633,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N' (' + CONVERT ( - varchar(10), - @version_date, + varchar(10), + @version_date, 101 ) + N')' @@ -649,7 +649,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ) VALUES (N'Server Name', @server_name); - + /* Using product version and level variables declared earlier */ INSERT INTO #server_info @@ -665,7 +665,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @product_level + N')' ); - + /* Using product edition variable declared earlier */ INSERT INTO #server_info @@ -680,7 +680,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) SELECT @@ -701,7 +701,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) SELECT @@ -745,7 +745,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -1071,7 +1071,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SELECT N'Memory Model', osi.sql_memory_model_desc - FROM sys.dm_os_sys_info AS osi; + FROM sys.dm_os_sys_info AS osi; END; /* Check if Instant File Initialization is enabled (on-prem only) */ @@ -1081,9 +1081,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AND @has_view_server_state = 1 BEGIN INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) SELECT @@ -1130,9 +1130,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IF EXISTS (SELECT 1/0 FROM sys.resource_governor_configuration AS rgc WHERE rgc.is_enabled = 1) BEGIN INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) SELECT @@ -1175,9 +1175,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ELSE BEGIN INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) SELECT @@ -1234,9 +1234,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IF EXISTS (SELECT 1/0 FROM #trace_flags AS tf WHERE tf.global = 1) BEGIN INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) SELECT @@ -1264,9 +1264,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Memory information - works on all platforms */ INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) SELECT @@ -1649,9 +1649,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IF @autogrow_summary IS NOT NULL BEGIN INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) VALUES @@ -2074,7 +2074,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2096,7 +2096,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2220,7 +2220,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2237,7 +2237,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2533,7 +2533,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2886,7 +2886,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) EXECUTE sys.sp_executesql @@ -2896,9 +2896,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN CATCH /* If we can't access the files due to permissions */ INSERT INTO - #server_info + #server_info ( - info_type, + info_type, value ) VALUES @@ -2935,7 +2935,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2948,7 +2948,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2972,7 +2972,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES @@ -2984,7 +2984,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. INSERT INTO #server_info ( - info_type, + info_type, value ) VALUES From 41eeb9644ec693cd1c7fd0b8bb2ad175feff3427 Mon Sep 17 00:00:00 2001 From: Darling Data Date: Thu, 17 Apr 2025 18:31:40 +0000 Subject: [PATCH 2/4] Automation: Format and Build SQL File --- Install-All/DarlingData.sql | 55 +++++++++++++++++---- sp_PerfCheck/sp_PerfCheck.sql | 14 +++--- sp_PressureDetector/sp_PressureDetector.sql | 8 +-- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/Install-All/DarlingData.sql b/Install-All/DarlingData.sql index 6ea6c2f8..d4e14191 100644 --- a/Install-All/DarlingData.sql +++ b/Install-All/DarlingData.sql @@ -1,4 +1,4 @@ --- Compile Date: 04/15/2025 00:27:51 UTC +-- Compile Date: 04/17/2025 18:31:39 UTC SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; @@ -24373,6 +24373,31 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ); END; + /* Check for percentage growth in tempdb */ + IF @has_percent_growth = 1 + BEGIN + INSERT INTO + #results + ( + check_id, + priority, + category, + finding, + details, + url + ) + VALUES + ( + 2006, + 50, /* High-medium priority */ + N'TempDB Configuration', + N'Percentage Auto-Growth Setting in TempDB', + N'TempDB data files are using percentage growth settings. This can lead to increasingly larger growth events as files grow. ' + + N'TempDB is recreated on server restart, so using predictable fixed-size growth is recommended for better performance.', + N'https://erikdarling.com/sp_PerfCheck#tempdb' + ); + END; + /* Memory configuration checks */ IF @min_server_memory >= (@max_server_memory * 0.9) /* Within 10% */ BEGIN @@ -25683,7 +25708,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. details = ''Database data file is using percentage growth setting ('' + CONVERT(nvarchar(20), mf.growth) + - ''%). This can lead to increasingly larger growth events as the file grows, + ''%). Current file size is '' + + CONVERT(nvarchar(20), CONVERT(decimal(18, 2), mf.size * 8.0 / 1024 / 1024)) + + '' GB. This can lead to increasingly larger growth events as the file grows, potentially causing larger file sizes than intended. Even with instant file initialization enabled, consider using a fixed size instead for more predictable growth.'', url = N''https://erikdarling.com/sp_PerfCheck#DataFileGrowth'' @@ -25817,7 +25844,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. object_name = mf.name, details = ''Database file is using a very large fixed growth increment of '' + - CONVERT(nvarchar(20), CONVERT(decimal(18, 2), mf.growth * 8.0 / 1024 / 1024)) + + CONVERT(nvarchar(20), + CONVERT(decimal(18, 2), mf.growth * + CONVERT(decimal(18, 2), 8.0) / + CONVERT(decimal(18, 2), 1024.0) / + CONVERT(decimal(18, 2), 1024.0))) + '' GB. Very large growth increments can lead to excessive space allocation. '' + CASE WHEN mf.type_desc = N''ROWS'' @@ -25828,7 +25859,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. url = N''https://erikdarling.com/sp_PerfCheck#LargeGrowth'' FROM ' + QUOTENAME(@current_database_name) + N'.sys.database_files AS mf WHERE mf.is_percent_growth = 0 - AND mf.growth * 8.0 / 1024 / 1024 > 10; /* Growth > 10GB */'; + AND mf.growth * CONVERT(decimal(18, 2), 8.0) / + CONVERT(decimal(18, 2), 1024.0) / + CONVERT(decimal(18, 2), 1024.0) > 10.0; /* Growth > 10GB */'; IF @debug = 1 BEGIN @@ -29572,7 +29605,7 @@ OPTION(MAXDOP 1, RECOMPILE);', @reserved_worker_count_out, N'0' ) - ELSE N'N/A' + ELSE N'''N/A''' END + N', threads_waiting_for_cpu = SUM(dos.runnable_tasks_count), @@ -29597,10 +29630,14 @@ OPTION(MAXDOP 1, RECOMPILE);', CROSS JOIN ( SELECT - active_request_count = SUM(wg.active_request_count), - queued_request_count = SUM(wg.queued_request_count), - blocked_task_count = SUM(wg.blocked_task_count), - active_parallel_thread_count = SUM(wg.active_parallel_thread_count) + active_request_count = + SUM(wg.active_request_count), + queued_request_count = + SUM(wg.queued_request_count), + blocked_task_count = + SUM(wg.blocked_task_count), + active_parallel_thread_count = + SUM(wg.active_parallel_thread_count) FROM sys.dm_resource_governor_workload_groups AS wg ) AS wg OUTER APPLY diff --git a/sp_PerfCheck/sp_PerfCheck.sql b/sp_PerfCheck/sp_PerfCheck.sql index da92b055..a9302a52 100644 --- a/sp_PerfCheck/sp_PerfCheck.sql +++ b/sp_PerfCheck/sp_PerfCheck.sql @@ -3400,7 +3400,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. N'https://erikdarling.com/sp_PerfCheck#tempdb' ); END; - + /* Check for percentage growth in tempdb */ IF @has_percent_growth = 1 BEGIN @@ -4872,10 +4872,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. object_name = mf.name, details = ''Database file is using a very large fixed growth increment of '' + - CONVERT(nvarchar(20), - CONVERT(decimal(18, 2), mf.growth * - CONVERT(decimal(18, 2), 8.0) / - CONVERT(decimal(18, 2), 1024.0) / + CONVERT(nvarchar(20), + CONVERT(decimal(18, 2), mf.growth * + CONVERT(decimal(18, 2), 8.0) / + CONVERT(decimal(18, 2), 1024.0) / CONVERT(decimal(18, 2), 1024.0))) + '' GB. Very large growth increments can lead to excessive space allocation. '' + CASE @@ -4887,8 +4887,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. url = N''https://erikdarling.com/sp_PerfCheck#LargeGrowth'' FROM ' + QUOTENAME(@current_database_name) + N'.sys.database_files AS mf WHERE mf.is_percent_growth = 0 - AND mf.growth * CONVERT(decimal(18, 2), 8.0) / - CONVERT(decimal(18, 2), 1024.0) / + AND mf.growth * CONVERT(decimal(18, 2), 8.0) / + CONVERT(decimal(18, 2), 1024.0) / CONVERT(decimal(18, 2), 1024.0) > 10.0; /* Growth > 10GB */'; IF @debug = 1 diff --git a/sp_PressureDetector/sp_PressureDetector.sql b/sp_PressureDetector/sp_PressureDetector.sql index fc6bcaf4..cae39486 100644 --- a/sp_PressureDetector/sp_PressureDetector.sql +++ b/sp_PressureDetector/sp_PressureDetector.sql @@ -3677,13 +3677,13 @@ OPTION(MAXDOP 1, RECOMPILE);', CROSS JOIN ( SELECT - active_request_count = + active_request_count = SUM(wg.active_request_count), - queued_request_count = + queued_request_count = SUM(wg.queued_request_count), - blocked_task_count = + blocked_task_count = SUM(wg.blocked_task_count), - active_parallel_thread_count = + active_parallel_thread_count = SUM(wg.active_parallel_thread_count) FROM sys.dm_resource_governor_workload_groups AS wg ) AS wg From 4ad282c6693d4b6264b2cdb2245cf45ae8580ddb Mon Sep 17 00:00:00 2001 From: Darling Data Date: Thu, 17 Apr 2025 21:22:02 +0000 Subject: [PATCH 3/4] Automation: Format and Build SQL File --- Install-All/DarlingData.sql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Install-All/DarlingData.sql b/Install-All/DarlingData.sql index d4e14191..71376807 100644 --- a/Install-All/DarlingData.sql +++ b/Install-All/DarlingData.sql @@ -1,4 +1,4 @@ --- Compile Date: 04/17/2025 18:31:39 UTC +-- Compile Date: 04/17/2025 21:22:01 UTC SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; @@ -4026,7 +4026,8 @@ END; error_number ) VALUES - (17830); + (17830), + (18056); SELECT event_time = From b63fca78489d45021a00347ac376969cbb85c2f4 Mon Sep 17 00:00:00 2001 From: Lars Platzdasch Date: Tue, 22 Apr 2025 16:55:23 +0200 Subject: [PATCH 4/4] Update sp_PerfCheck.sql fix the Conversion Error where the Database size is in TB Msg 8115, Level 16, State 2, Procedure dbo.sp_PerfCheck, Line 1980 [Batch Start Line 2] Arithmetic overflow error converting expression to data type int. --- sp_PerfCheck/sp_PerfCheck.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp_PerfCheck/sp_PerfCheck.sql b/sp_PerfCheck/sp_PerfCheck.sql index a9302a52..3a036ac4 100644 --- a/sp_PerfCheck/sp_PerfCheck.sql +++ b/sp_PerfCheck/sp_PerfCheck.sql @@ -2381,7 +2381,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THEN 0 ELSE CONVERT(decimal(18, 2), SUM(fs.io_stall_write_ms) * 1.0 / SUM(fs.num_of_writes)) END, - total_size_mb = CONVERT(decimal(18, 2), SUM(mf.size) * 8.0 / 1024.0) + total_size_mb = CONVERT(decimal(18, 2), SUM(CAST(mf.size as BIGINT)) * 8.0 / 1024.0) FROM sys.dm_io_virtual_file_stats (' + CASE