Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Dashboard/Dashboard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
<UseWPF>true</UseWPF>
<AssemblyName>PerformanceMonitorDashboard</AssemblyName>
<Product>SQL Server Performance Monitor Dashboard</Product>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<InformationalVersion>2.1.0</InformationalVersion>
<Version>2.2.0</Version>
<AssemblyVersion>2.2.0.0</AssemblyVersion>
<FileVersion>2.2.0.0</FileVersion>
<InformationalVersion>2.2.0</InformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<ApplicationIcon>EDD.ico</ApplicationIcon>
Expand Down
16 changes: 8 additions & 8 deletions Dashboard/Services/DatabaseService.QueryPerformance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -739,8 +739,8 @@ WITH per_lifetime AS
total_spills = MAX(qs.total_spills),
min_spills = MIN(qs.min_spills),
max_spills = MAX(qs.max_spills),
query_text = MAX(qs.query_text),
query_plan_text = MAX(qs.query_plan_text),
query_text = CAST(DECOMPRESS(MAX(qs.query_text)) AS nvarchar(max)),
query_plan_text = CAST(DECOMPRESS(MAX(qs.query_plan_text)) AS nvarchar(max)),
query_plan_hash = MAX(qs.query_plan_hash),
sql_handle = MAX(qs.sql_handle),
plan_handle = MAX(qs.plan_handle)
Expand All @@ -753,7 +753,7 @@ FROM collect.query_stats AS qs
OR (qs.last_execution_time >= @fromDate AND qs.last_execution_time <= @toDate)
OR (qs.creation_time <= @fromDate AND qs.last_execution_time >= @toDate)))
)
AND qs.query_text NOT LIKE N'WAITFOR%'
AND CAST(DECOMPRESS(qs.query_text) AS nvarchar(max)) NOT LIKE N'WAITFOR%'
GROUP BY
qs.database_name,
qs.query_hash,
Expand Down Expand Up @@ -922,7 +922,7 @@ WITH per_lifetime AS
total_spills = MAX(ps.total_spills),
min_spills = MIN(ps.min_spills),
max_spills = MAX(ps.max_spills),
query_plan_text = MAX(ps.query_plan_text),
query_plan_text = CAST(DECOMPRESS(MAX(ps.query_plan_text)) AS nvarchar(max)),
sql_handle = MAX(ps.sql_handle),
plan_handle = MAX(ps.plan_handle)
FROM collect.procedure_stats AS ps
Expand Down Expand Up @@ -1101,7 +1101,7 @@ public async Task<List<QueryStoreItem>> GetQueryStoreDataAsync(int hoursBack = 2
plan_type = MAX(qsd.plan_type),
is_forced_plan = MAX(CONVERT(tinyint, qsd.is_forced_plan)),
compatibility_level = MAX(qsd.compatibility_level),
query_sql_text = CONVERT(nvarchar(max), MAX(qsd.query_sql_text)),
query_sql_text = CAST(DECOMPRESS(MAX(qsd.query_sql_text)) AS nvarchar(max)),
query_plan_hash = CONVERT(nvarchar(20), MAX(qsd.query_plan_hash), 1),
force_failure_count = SUM(qsd.force_failure_count),
last_force_failure_reason_desc = MAX(qsd.last_force_failure_reason_desc),
Expand All @@ -1121,7 +1121,7 @@ FROM collect.query_store_data AS qsd
OR (qsd.server_last_execution_time >= @fromDate AND qsd.server_last_execution_time <= @toDate)
OR (qsd.server_first_execution_time <= @fromDate AND qsd.server_last_execution_time >= @toDate)))
)
AND qsd.query_sql_text NOT LIKE N'WAITFOR%'
AND CAST(DECOMPRESS(qsd.query_sql_text) AS nvarchar(max)) NOT LIKE N'WAITFOR%'
GROUP BY
qsd.database_name,
qsd.query_id
Expand Down Expand Up @@ -2228,7 +2228,7 @@ ORDER BY
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT
qsd.query_plan_text
CAST(DECOMPRESS(qsd.query_plan_text) AS nvarchar(max)) AS query_plan_text
FROM collect.query_store_data AS qsd
WHERE qsd.collection_id = @collection_id;";

Expand Down Expand Up @@ -2276,7 +2276,7 @@ FROM collect.procedure_stats AS ps
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT
qs.query_plan_text
CAST(DECOMPRESS(qs.query_plan_text) AS nvarchar(max)) AS query_plan_text
FROM collect.query_stats AS qs
WHERE qs.collection_id = @collection_id;";

Expand Down
8 changes: 4 additions & 4 deletions Installer/PerformanceMonitorInstaller.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
<!-- Application metadata -->
<AssemblyName>PerformanceMonitorInstaller</AssemblyName>
<Product>SQL Server Performance Monitor Installer</Product>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<InformationalVersion>2.1.0</InformationalVersion>
<Version>2.2.0</Version>
<AssemblyVersion>2.2.0.0</AssemblyVersion>
<FileVersion>2.2.0.0</FileVersion>
<InformationalVersion>2.2.0</InformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<Description>Installation utility for SQL Server Performance Monitor - Supports SQL Server 2016-2025</Description>
Expand Down
8 changes: 4 additions & 4 deletions InstallerGui/InstallerGui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<AssemblyName>PerformanceMonitorInstallerGui</AssemblyName>
<RootNamespace>PerformanceMonitorInstallerGui</RootNamespace>
<Product>SQL Server Performance Monitor Installer</Product>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<InformationalVersion>2.1.0</InformationalVersion>
<Version>2.2.0</Version>
<AssemblyVersion>2.2.0.0</AssemblyVersion>
<FileVersion>2.2.0.0</FileVersion>
<InformationalVersion>2.2.0</InformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<ApplicationIcon>EDD.ico</ApplicationIcon>
Expand Down
8 changes: 4 additions & 4 deletions Lite/PerformanceMonitorLite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<AssemblyName>PerformanceMonitorLite</AssemblyName>
<RootNamespace>PerformanceMonitorLite</RootNamespace>
<Product>SQL Server Performance Monitor Lite</Product>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<InformationalVersion>2.1.0</InformationalVersion>
<Version>2.2.0</Version>
<AssemblyVersion>2.2.0.0</AssemblyVersion>
<FileVersion>2.2.0.0</FileVersion>
<InformationalVersion>2.2.0</InformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<Description>Lightweight SQL Server performance monitoring - no installation required on target servers</Description>
Expand Down
4 changes: 4 additions & 0 deletions install/01_install_database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ BEGIN
DEFAULT 5,
retention_days integer NOT NULL
DEFAULT 30,
collect_query bit NOT NULL
DEFAULT CONVERT(bit, 'true'),
collect_plan bit NOT NULL
DEFAULT CONVERT(bit, 'true'),
[description] nvarchar(500) NULL,
created_date datetime2(7) NOT NULL
DEFAULT SYSDATETIME(),
Expand Down
104 changes: 94 additions & 10 deletions install/02_create_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,11 @@ BEGIN
total_worker_time_delta /
NULLIF(sample_interval_seconds, 0) / 1000.
),
/*Query text and execution plan*/
query_text nvarchar(MAX) NULL,
query_plan_text nvarchar(MAX) NULL,
query_plan xml NULL,
/*Query text and execution plan (compressed with COMPRESS/DECOMPRESS)*/
query_text varbinary(max) NULL,
query_plan_text varbinary(max) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_query_stats
PRIMARY KEY CLUSTERED
Expand All @@ -183,6 +184,34 @@ BEGIN
PRINT 'Created collect.query_stats table';
END;

/*
2b. Query Stats Dedup Tracking
One row per natural key, updated on each collection cycle
*/
IF OBJECT_ID(N'collect.query_stats_latest_hash', N'U') IS NULL
BEGIN
CREATE TABLE
collect.query_stats_latest_hash
(
sql_handle varbinary(64) NOT NULL,
statement_start_offset integer NOT NULL,
statement_end_offset integer NOT NULL,
plan_handle varbinary(64) NOT NULL,
row_hash binary(32) NOT NULL,
last_seen datetime2(7) NOT NULL
DEFAULT SYSDATETIME(),
CONSTRAINT
PK_query_stats_latest_hash
PRIMARY KEY CLUSTERED
(sql_handle, statement_start_offset,
statement_end_offset, plan_handle)
WITH
(DATA_COMPRESSION = PAGE)
);

PRINT 'Created collect.query_stats_latest_hash table';
END;

/*
3. Memory Pressure
*/
Expand Down Expand Up @@ -429,9 +458,10 @@ BEGIN
total_worker_time_delta /
NULLIF(sample_interval_seconds, 0) / 1000.
),
/*Execution plan*/
query_plan_text nvarchar(max) NULL,
query_plan xml NULL,
/*Execution plan (compressed with COMPRESS/DECOMPRESS)*/
query_plan_text varbinary(max) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_procedure_stats
PRIMARY KEY CLUSTERED
Expand All @@ -443,6 +473,32 @@ BEGIN
PRINT 'Created collect.procedure_stats table';
END;

/*
9b. Procedure Stats Dedup Tracking
One row per natural key, updated on each collection cycle
*/
IF OBJECT_ID(N'collect.procedure_stats_latest_hash', N'U') IS NULL
BEGIN
CREATE TABLE
collect.procedure_stats_latest_hash
(
database_name sysname NOT NULL,
object_id integer NOT NULL,
plan_handle varbinary(64) NOT NULL,
row_hash binary(32) NOT NULL,
last_seen datetime2(7) NOT NULL
DEFAULT SYSDATETIME(),
CONSTRAINT
PK_procedure_stats_latest_hash
PRIMARY KEY CLUSTERED
(database_name, object_id, plan_handle)
WITH
(DATA_COMPRESSION = PAGE)
);

PRINT 'Created collect.procedure_stats_latest_hash table';
END;

/*
10. Currently Executing Query Snapshots
Table is created dynamically by sp_WhoIsActive on first collection
Expand Down Expand Up @@ -473,7 +529,7 @@ BEGIN
server_first_execution_time datetime2(7) NOT NULL,
server_last_execution_time datetime2(7) NOT NULL,
module_name nvarchar(261) NULL,
query_sql_text nvarchar(max) NULL,
query_sql_text varbinary(max) NULL,
query_hash binary(8) NULL,
/*Execution count*/
count_executions bigint NOT NULL,
Expand Down Expand Up @@ -531,9 +587,11 @@ BEGIN
last_force_failure_reason_desc nvarchar(128) NULL,
plan_forcing_type nvarchar(60) NULL,
compatibility_level smallint NULL,
query_plan_text nvarchar(max) NULL,
compilation_metrics xml NULL,
query_plan_text varbinary(max) NULL,
compilation_metrics varbinary(max) NULL,
query_plan_hash binary(8) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_query_store_data
PRIMARY KEY CLUSTERED
Expand All @@ -545,6 +603,32 @@ BEGIN
PRINT 'Created collect.query_store_data table';
END;

/*
11b. Query Store Data Dedup Tracking
One row per natural key, updated on each collection cycle
*/
IF OBJECT_ID(N'collect.query_store_data_latest_hash', N'U') IS NULL
BEGIN
CREATE TABLE
collect.query_store_data_latest_hash
(
database_name sysname NOT NULL,
query_id bigint NOT NULL,
plan_id bigint NOT NULL,
row_hash binary(32) NOT NULL,
last_seen datetime2(7) NOT NULL
DEFAULT SYSDATETIME(),
CONSTRAINT
PK_query_store_data_latest_hash
PRIMARY KEY CLUSTERED
(database_name, query_id, plan_id)
WITH
(DATA_COMPRESSION = PAGE)
);

PRINT 'Created collect.query_store_data_latest_hash table';
END;

/*
Trace analysis table - stores processed trace file data
*/
Expand Down
24 changes: 14 additions & 10 deletions install/06_ensure_collection_table.sql
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,11 @@ BEGIN
total_worker_time_delta /
NULLIF(sample_interval_seconds, 0) / 1000.
),
/*Query text and execution plan*/
query_text nvarchar(max) NULL,
query_plan_text nvarchar(max) NULL,
query_plan xml NULL,
/*Query text and execution plan (compressed with COMPRESS/DECOMPRESS)*/
query_text varbinary(max) NULL,
query_plan_text varbinary(max) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_query_stats
PRIMARY KEY CLUSTERED
Expand Down Expand Up @@ -446,9 +447,10 @@ BEGIN
total_worker_time_delta /
NULLIF(sample_interval_seconds, 0) / 1000.
),
/*Execution plan*/
query_plan_text nvarchar(max) NULL,
query_plan xml NULL,
/*Execution plan (compressed with COMPRESS/DECOMPRESS)*/
query_plan_text varbinary(max) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_procedure_stats
PRIMARY KEY CLUSTERED
Expand Down Expand Up @@ -491,7 +493,7 @@ BEGIN
server_first_execution_time datetime2(7) NOT NULL,
server_last_execution_time datetime2(7) NOT NULL,
module_name nvarchar(261) NULL,
query_sql_text nvarchar(max) NULL,
query_sql_text varbinary(max) NULL,
query_hash binary(8) NULL,
/*Execution count*/
count_executions bigint NOT NULL,
Expand Down Expand Up @@ -549,9 +551,11 @@ BEGIN
last_force_failure_reason_desc nvarchar(128) NULL,
plan_forcing_type nvarchar(60) NULL,
compatibility_level smallint NULL,
query_plan_text nvarchar(max) NULL,
compilation_metrics xml NULL,
query_plan_text varbinary(max) NULL,
compilation_metrics varbinary(max) NULL,
query_plan_hash binary(8) NULL,
/*Deduplication hash for skipping unchanged rows*/
row_hash binary(32) NULL,
CONSTRAINT
PK_query_store_data
PRIMARY KEY CLUSTERED
Expand Down
Loading
Loading