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();