diff --git a/Dashboard/Controls/MemoryContent.xaml b/Dashboard/Controls/MemoryContent.xaml index bae6cf3b..d157b62a 100644 --- a/Dashboard/Controls/MemoryContent.xaml +++ b/Dashboard/Controls/MemoryContent.xaml @@ -49,18 +49,45 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Dashboard/Controls/MemoryContent.xaml.cs b/Dashboard/Controls/MemoryContent.xaml.cs index 2ce4ee10..5ce7ee3b 100644 --- a/Dashboard/Controls/MemoryContent.xaml.cs +++ b/Dashboard/Controls/MemoryContent.xaml.cs @@ -333,6 +333,9 @@ private void UpdateMemoryStatsSummaryPanel(List dataList) { if (dataList == null || dataList.Count == 0) { + MemoryStatsPhysicalText.Text = "N/A"; + MemoryStatsSqlServerText.Text = "N/A"; + MemoryStatsTargetText.Text = "N/A"; MemoryStatsBPPercentText.Text = "N/A"; MemoryStatsPCPercentText.Text = "N/A"; MemoryStatsUtilPercentText.Text = "N/A"; @@ -344,14 +347,26 @@ private void UpdateMemoryStatsSummaryPanel(List dataList) // Use the most recent data point var latest = dataList.OrderByDescending(d => d.CollectionTime).First(); - MemoryStatsBPPercentText.Text = latest.BufferPoolPercentage.HasValue - ? $"{latest.BufferPoolPercentage:F1}%" + // Absolute GB values + MemoryStatsPhysicalText.Text = latest.TotalPhysicalMemoryMb.HasValue + ? $"{latest.TotalPhysicalMemoryMb.Value / 1024.0m:F1} GB" : "N/A"; - MemoryStatsPCPercentText.Text = latest.PlanCachePercentage.HasValue - ? $"{latest.PlanCachePercentage:F1}%" + MemoryStatsSqlServerText.Text = $"{latest.PhysicalMemoryInUseMb / 1024.0m:F1} GB"; + + MemoryStatsTargetText.Text = latest.CommittedTargetMemoryMb.HasValue + ? $"{latest.CommittedTargetMemoryMb.Value / 1024.0m:F1} GB" : "N/A"; + // Buffer Pool and Plan Cache with GB and percentage + MemoryStatsBPPercentText.Text = latest.BufferPoolPercentage.HasValue + ? $"{latest.BufferPoolMb / 1024.0m:F1} GB ({latest.BufferPoolPercentage:F1}%)" + : $"{latest.BufferPoolMb / 1024.0m:F1} GB"; + + MemoryStatsPCPercentText.Text = latest.PlanCachePercentage.HasValue + ? $"{latest.PlanCacheMb / 1024.0m:F1} GB ({latest.PlanCachePercentage:F1}%)" + : $"{latest.PlanCacheMb / 1024.0m:F1} GB"; + MemoryStatsUtilPercentText.Text = $"{latest.MemoryUtilizationPercentage}%"; // Build pressure status text diff --git a/Dashboard/Models/MemoryStatsItem.cs b/Dashboard/Models/MemoryStatsItem.cs index 45d5bb96..92a26421 100644 --- a/Dashboard/Models/MemoryStatsItem.cs +++ b/Dashboard/Models/MemoryStatsItem.cs @@ -18,6 +18,10 @@ public class MemoryStatsItem public decimal AvailablePhysicalMemoryMb { get; set; } public int MemoryUtilizationPercentage { get; set; } + // Server and target memory + public decimal? TotalPhysicalMemoryMb { get; set; } + public decimal? CommittedTargetMemoryMb { get; set; } + // Pressure warnings public bool BufferPoolPressureWarning { get; set; } public bool PlanCachePressureWarning { get; set; } diff --git a/Dashboard/Services/DatabaseService.Memory.cs b/Dashboard/Services/DatabaseService.Memory.cs index eb05205f..28a4d00e 100644 --- a/Dashboard/Services/DatabaseService.Memory.cs +++ b/Dashboard/Services/DatabaseService.Memory.cs @@ -46,7 +46,9 @@ public async Task> GetMemoryStatsAsync(int hoursBack = 24, ms.available_physical_memory_mb, ms.memory_utilization_percentage, ms.buffer_pool_pressure_warning, - ms.plan_cache_pressure_warning + ms.plan_cache_pressure_warning, + ms.total_physical_memory_mb, + ms.committed_target_memory_mb FROM collect.memory_stats AS ms {dateFilter} ORDER BY @@ -80,7 +82,9 @@ ORDER BY AvailablePhysicalMemoryMb = reader.GetDecimal(7), MemoryUtilizationPercentage = reader.GetInt32(8), BufferPoolPressureWarning = reader.GetBoolean(9), - PlanCachePressureWarning = reader.GetBoolean(10) + PlanCachePressureWarning = reader.GetBoolean(10), + TotalPhysicalMemoryMb = reader.IsDBNull(11) ? null : reader.GetDecimal(11), + CommittedTargetMemoryMb = reader.IsDBNull(12) ? null : reader.GetDecimal(12) }); } diff --git a/install/02_create_tables.sql b/install/02_create_tables.sql index e25923e3..c053fcab 100644 --- a/install/02_create_tables.sql +++ b/install/02_create_tables.sql @@ -194,6 +194,9 @@ BEGIN physical_memory_in_use_mb decimal(19,2) NOT NULL, available_physical_memory_mb decimal(19,2) NOT NULL, memory_utilization_percentage integer NOT NULL, + /*Server and target memory*/ + total_physical_memory_mb decimal(19,2) NULL, + committed_target_memory_mb decimal(19,2) NULL, /*Pressure warnings*/ buffer_pool_pressure_warning bit NOT NULL DEFAULT 0, plan_cache_pressure_warning bit NOT NULL DEFAULT 0, @@ -219,6 +222,19 @@ BEGIN PRINT 'Created collect.memory_stats table'; END; +/*Add columns for existing installs*/ +IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'collect.memory_stats') AND name = N'total_physical_memory_mb') +BEGIN + ALTER TABLE collect.memory_stats ADD total_physical_memory_mb decimal(19,2) NULL; + PRINT 'Added total_physical_memory_mb to collect.memory_stats'; +END; + +IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'collect.memory_stats') AND name = N'committed_target_memory_mb') +BEGIN + ALTER TABLE collect.memory_stats ADD committed_target_memory_mb decimal(19,2) NULL; + PRINT 'Added committed_target_memory_mb to collect.memory_stats'; +END; + /* 4. I/O Performance - handled by sp_PressureDetector NOTE: I/O metrics are collected by sp_PressureDetector into collect.PressureDetector_FileMetrics diff --git a/install/06_ensure_collection_table.sql b/install/06_ensure_collection_table.sql index f5e23e73..0b7a9407 100644 --- a/install/06_ensure_collection_table.sql +++ b/install/06_ensure_collection_table.sql @@ -294,6 +294,9 @@ BEGIN physical_memory_in_use_mb decimal(19,2) NOT NULL, available_physical_memory_mb decimal(19,2) NOT NULL, memory_utilization_percentage integer NOT NULL, + /*Server and target memory*/ + total_physical_memory_mb decimal(19,2) NULL, + committed_target_memory_mb decimal(19,2) NULL, /*Pressure warnings*/ buffer_pool_pressure_warning bit NOT NULL DEFAULT 0, plan_cache_pressure_warning bit NOT NULL DEFAULT 0, @@ -307,12 +310,12 @@ BEGIN ( plan_cache_mb * 100.0 / NULLIF(total_memory_mb, 0) - ), - CONSTRAINT - PK_memory_stats - PRIMARY KEY CLUSTERED - (collection_time, collection_id) - WITH + ), + CONSTRAINT + PK_memory_stats + PRIMARY KEY CLUSTERED + (collection_time, collection_id) + WITH (DATA_COMPRESSION = PAGE) ); END; diff --git a/install/14_collect_memory_stats.sql b/install/14_collect_memory_stats.sql index d0f5bd48..a1ebcde5 100644 --- a/install/14_collect_memory_stats.sql +++ b/install/14_collect_memory_stats.sql @@ -169,8 +169,15 @@ BEGIN system_memory AS ( SELECT - available_physical_memory_mb = sm.available_physical_memory_kb / 1024.0 + available_physical_memory_mb = sm.available_physical_memory_kb / 1024.0, + total_physical_memory_mb = sm.total_physical_memory_kb / 1024.0 FROM sys.dm_os_sys_memory AS sm + ), + system_info AS + ( + SELECT + committed_target_memory_mb = si.committed_target_kb / 1024.0 + FROM sys.dm_os_sys_info AS si ) INSERT INTO collect.memory_stats @@ -182,6 +189,8 @@ BEGIN physical_memory_in_use_mb, available_physical_memory_mb, memory_utilization_percentage, + total_physical_memory_mb, + committed_target_memory_mb, buffer_pool_pressure_warning, plan_cache_pressure_warning ) @@ -193,6 +202,8 @@ BEGIN physical_memory_in_use_mb = pm.physical_memory_in_use_mb, available_physical_memory_mb = sm.available_physical_memory_mb, memory_utilization_percentage = pm.memory_utilization_percentage, + total_physical_memory_mb = sm.total_physical_memory_mb, + committed_target_memory_mb = si.committed_target_memory_mb, buffer_pool_pressure_warning = CASE WHEN @previous_buffer_pool_mb IS NOT NULL @@ -210,6 +221,7 @@ BEGIN FROM memory_clerks AS mc CROSS JOIN process_memory AS pm CROSS JOIN system_memory AS sm + CROSS JOIN system_info AS si OPTION(RECOMPILE); SET @rows_collected = ROWCOUNT_BIG();