From 1ab3c313fe348bb1f3955fc2277c7ab0b7b707c3 Mon Sep 17 00:00:00 2001 From: Darling Data Date: Sat, 4 Apr 2026 15:20:35 +0000 Subject: [PATCH 1/2] Automation: Format and Build SQL File [skip ci] --- Install-All/DarlingData.sql | 137 +++++++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 25 deletions(-) diff --git a/Install-All/DarlingData.sql b/Install-All/DarlingData.sql index 1375f44b..b75e2ef9 100644 --- a/Install-All/DarlingData.sql +++ b/Install-All/DarlingData.sql @@ -1,4 +1,4 @@ --- Compile Date: 04/04/2026 14:58:35 UTC +-- Compile Date: 04/04/2026 15:20:33 UTC SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; @@ -172,6 +172,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_HealthParser' + ORDER BY + ap.parameter_id OPTION(RECOMPILE); SELECT @@ -6480,7 +6482,10 @@ BEGIN JOIN sys.types AS t ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id - WHERE o.name = N'sp_HumanEvents'; + WHERE o.name = N'sp_HumanEvents' + ORDER BY + ap.parameter_id + OPTION(RECOMPILE); /*Example calls*/ @@ -11370,6 +11375,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_HumanEventsBlockViewer' + ORDER BY + ap.parameter_id OPTION(RECOMPILE); SELECT @@ -15155,6 +15162,8 @@ BEGIN TRY ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_IndexCleanup' + ORDER BY + ap.parameter_id OPTION(MAXDOP 1, RECOMPILE); SELECT @@ -22198,6 +22207,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_LogHunter' + ORDER BY + ap.parameter_id OPTION(RECOMPILE); SELECT @@ -22929,6 +22940,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_PerfCheck' + ORDER BY + ap.parameter_id OPTION(MAXDOP 1, RECOMPILE); SELECT @@ -28064,6 +28077,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_PressureDetector' + ORDER BY + ap.parameter_id OPTION(MAXDOP 1, RECOMPILE); SELECT @@ -32571,6 +32586,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_QueryReproBuilder' + ORDER BY + ap.parameter_id OPTION(RECOMPILE); RETURN; @@ -36437,7 +36454,7 @@ GO ALTER PROCEDURE dbo.sp_QuickieCache ( - @top integer = 10, /*candidates per metric dimension before dedup*/ + @top bigint = 10, /*candidates per metric dimension before dedup*/ @sort_order varchar(20) = 'cpu', /*secondary sort after impact_score: cpu, duration, reads, writes, memory, spills, executions*/ @database_name sysname = NULL, /*filter to a specific database*/ @start_date datetime = NULL, /*only include plans created after this date*/ @@ -36467,6 +36484,21 @@ BEGIN */ IF @help = 1 BEGIN + /* + Introduction + */ + SELECT + introduction = + 'hi, i''m sp_QuickieCache!' UNION ALL + SELECT 'you got me from https://code.erikdarling.com' UNION ALL + SELECT 'i analyze the plan cache to find the vital few queries consuming disproportionate resources' UNION ALL + SELECT 'think of me as the plan cache companion to sp_QuickieStore' UNION ALL + SELECT 'i score queries across 7 dimensions using Pareto (80/20) analysis' UNION ALL + SELECT 'from your loving sql server consultant, erik darling: https://erikdarling.com'; + + /* + Parameters + */ SELECT parameter_name = ap.name, @@ -36475,44 +36507,97 @@ BEGIN description = CASE ap.name WHEN N'@top' - THEN N'Number of candidate queries per metric dimension (cpu, reads, etc.) before dedup. Default: 10.' + THEN N'candidates per metric dimension before dedup' WHEN N'@sort_order' - THEN N'Secondary sort after impact_score. Options: cpu, duration, reads, writes, memory, spills, executions. Default: cpu.' + THEN N'secondary sort after impact_score' WHEN N'@database_name' - THEN N'Filter to a specific database. Default: NULL (all user databases).' + THEN N'filter to a specific database' WHEN N'@start_date' - THEN N'Only include plans created after this date. Default: NULL (no filter).' + THEN N'only include plans created after this date' WHEN N'@end_date' - THEN N'Only include plans created before this date. Default: NULL (no filter).' + THEN N'only include plans created before this date' WHEN N'@minimum_execution_count' - THEN N'Minimum execution count to include a query. Filters single-execution noise. Default: 2.' + THEN N'minimum execution count to include a query' WHEN N'@ignore_system_databases' - THEN N'Exclude system databases (master, model, msdb, tempdb). Default: 1.' + THEN N'exclude system databases (master, model, msdb, tempdb)' WHEN N'@impact_threshold' - THEN N'Minimum impact_score (0.00-1.00) to surface in results. Default: 0.50.' + THEN N'minimum impact_score to surface in results' WHEN N'@debug' - THEN N'Print diagnostic information. Default: 0.' + THEN N'print diagnostic information' WHEN N'@help' - THEN N'You are here. Default: 0.' + THEN N'how you got here' WHEN N'@version' - THEN N'OUTPUT; for support.' + THEN N'OUTPUT; for support' WHEN N'@version_date' - THEN N'OUTPUT; for support.' + THEN N'OUTPUT; for support' + ELSE N'' + END, + valid_inputs = + CASE ap.name + WHEN N'@top' + THEN N'a positive integer' + WHEN N'@sort_order' + THEN N'cpu, duration, reads, writes, memory, spills, executions' + WHEN N'@database_name' + THEN N'a valid database name' + WHEN N'@start_date' + THEN N'a valid datetime' + WHEN N'@end_date' + THEN N'a valid datetime' + WHEN N'@minimum_execution_count' + THEN N'a positive integer' + WHEN N'@ignore_system_databases' + THEN N'0 or 1' + WHEN N'@impact_threshold' + THEN N'0.00 to 1.00' + WHEN N'@debug' + THEN N'0 or 1' + WHEN N'@help' + THEN N'0 or 1' + WHEN N'@version' + THEN N'none; OUTPUT' + WHEN N'@version_date' + THEN N'none; OUTPUT' + ELSE N'' + END, + defaults = + CASE ap.name + WHEN N'@top' + THEN N'10' + WHEN N'@sort_order' + THEN N'cpu' + WHEN N'@database_name' + THEN N'NULL' + WHEN N'@start_date' + THEN N'NULL' + WHEN N'@end_date' + THEN N'NULL' + WHEN N'@minimum_execution_count' + THEN N'2' + WHEN N'@ignore_system_databases' + THEN N'1' + WHEN N'@impact_threshold' + THEN N'0.50' + WHEN N'@debug' + THEN N'0' + WHEN N'@help' + THEN N'0' + WHEN N'@version' + THEN N'none; OUTPUT' + WHEN N'@version_date' + THEN N'none; OUTPUT' ELSE N'' END FROM sys.all_parameters AS ap + JOIN sys.all_objects AS o + ON ap.object_id = o.object_id JOIN sys.types AS t - ON t.user_type_id = ap.user_type_id - WHERE ap.object_id = @@PROCID + ON ap.system_type_id = t.system_type_id + AND ap.user_type_id = t.user_type_id + WHERE o.name = N'sp_QuickieCache' ORDER BY - ap.parameter_id; - - SELECT - methodology = N'Pareto (80/20) analysis across 7 resource dimensions', - dimensions = N'CPU, Duration, Logical Reads, Logical Writes, Memory Grants, Spills, Executions', - scoring = N'PERCENT_RANK per dimension, averaged across active dimensions (>= 0.1% of total)', - high_signal = N'Dimensions where query ranks >= 80th percentile', - output = N'Queries with impact_score >= @impact_threshold, plus workload profile summary'; + ap.parameter_id + OPTION(MAXDOP 1, RECOMPILE); /* License to F5 @@ -38758,6 +38843,8 @@ BEGIN ON ap.system_type_id = t.system_type_id AND ap.user_type_id = t.user_type_id WHERE o.name = N'sp_QuickieStore' + ORDER BY + ap.parameter_id OPTION(RECOMPILE); /* From 6443e4d6adb1ab4b7b6870f688db715453a5cc27 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Sat, 4 Apr 2026 11:43:21 -0400 Subject: [PATCH 2/2] sp_QuickieCache: add single-use/duplicate plan modes, fix @ignore_system_databases - Add @find_single_use_plans: shows largest single-use plans by cached size - Add @find_duplicate_plans: shows query hashes with multiple cached plans - All system database filters now respect @ignore_system_databases flag (previously hardcoded in health findings and new modes) Co-Authored-By: Claude Opus 4.6 (1M context) --- sp_QuickieCache/sp_QuickieCache.sql | 146 +++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 2 deletions(-) diff --git a/sp_QuickieCache/sp_QuickieCache.sql b/sp_QuickieCache/sp_QuickieCache.sql index d41323a8..88575774 100644 --- a/sp_QuickieCache/sp_QuickieCache.sql +++ b/sp_QuickieCache/sp_QuickieCache.sql @@ -62,6 +62,8 @@ ALTER PROCEDURE @minimum_execution_count bigint = 2, /*noise floor for single-exec queries*/ @ignore_system_databases bit = 1, /*exclude master, model, msdb, tempdb*/ @impact_threshold decimal(3, 2) = 0.50, /*minimum impact_score to surface (0.00-1.00)*/ + @find_single_use_plans bit = 0, /*show single-use plans consuming the most memory*/ + @find_duplicate_plans bit = 0, /*show query hashes with multiple cached plans*/ @debug bit = 0, /*print diagnostics*/ @help bit = 0, /*display parameter help*/ @version varchar(30) = NULL OUTPUT, /*OUTPUT; for support*/ @@ -122,6 +124,10 @@ BEGIN THEN N'exclude system databases (master, model, msdb, tempdb)' WHEN N'@impact_threshold' THEN N'minimum impact_score to surface in results' + WHEN N'@find_single_use_plans' + THEN N'show single-use plans consuming the most memory' + WHEN N'@find_duplicate_plans' + THEN N'show query hashes with multiple cached plans' WHEN N'@debug' THEN N'print diagnostic information' WHEN N'@help' @@ -150,6 +156,10 @@ BEGIN THEN N'0 or 1' WHEN N'@impact_threshold' THEN N'0.00 to 1.00' + WHEN N'@find_single_use_plans' + THEN N'0 or 1' + WHEN N'@find_duplicate_plans' + THEN N'0 or 1' WHEN N'@debug' THEN N'0 or 1' WHEN N'@help' @@ -178,6 +188,10 @@ BEGIN THEN N'1' WHEN N'@impact_threshold' THEN N'0.50' + WHEN N'@find_single_use_plans' + THEN N'0' + WHEN N'@find_duplicate_plans' + THEN N'0' WHEN N'@debug' THEN N'0' WHEN N'@help' @@ -326,6 +340,134 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. RETURN; END; + /* + ╔══════════════════════════════════════════════════╗ + ║ Single-use plans mode ║ + ╚══════════════════════════════════════════════════╝ + + Shows the largest single-use plans by cached size, + sorted by memory consumption descending. + */ + IF @find_single_use_plans = 1 + BEGIN + SELECT TOP (@top) + database_name = + DB_NAME(CONVERT(integer, pa.value)), + cached_plan_size_kb = + cp.size_in_bytes / 1024, + query_text = + st.text, + query_plan = + CASE + WHEN TRY_CAST(qp.query_plan AS xml) IS NOT NULL + THEN TRY_CAST(qp.query_plan AS xml) + WHEN TRY_CAST(qp.query_plan AS xml) IS NULL + THEN + ( + SELECT + [processing-instruction(query_plan)] = + N'-- ' + NCHAR(13) + NCHAR(10) + + N'-- This is a huge query plan.' + NCHAR(13) + NCHAR(10) + + N'-- Remove the headers and footers, save it as a .sqlplan file, and re-open it.' + NCHAR(13) + NCHAR(10) + + NCHAR(13) + NCHAR(10) + + REPLACE(qp.query_plan, N' 0x0000000000000000 + AND (@ignore_system_databases = 0 OR ISNULL(CONVERT(integer, pa.value), 0) NOT IN (1, 2, 3, 4)) + AND ISNULL(CONVERT(integer, pa.value), 0) < 32761 + AND (@database_id IS NULL OR CONVERT(integer, pa.value) = @database_id) + GROUP BY + qs.query_hash + HAVING + COUNT_BIG(DISTINCT qs.plan_handle) > 1 + ORDER BY + COUNT_BIG(DISTINCT qs.plan_handle) DESC + OPTION(RECOMPILE, MAXDOP 1); + + RETURN; + END; + /* ╔══════════════════════════════════════════════════╗ ║ Plan cache health analysis ║ @@ -537,7 +679,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WHERE pa.attribute = N'dbid' ) AS pa WHERE pa.value IS NOT NULL - AND CONVERT(integer, pa.value) NOT IN (1, 2, 3, 4) + AND (@ignore_system_databases = 0 OR CONVERT(integer, pa.value) NOT IN (1, 2, 3, 4)) AND CONVERT(integer, pa.value) < 32761 AND (@database_id IS NULL OR CONVERT(integer, pa.value) = @database_id) GROUP BY @@ -646,7 +788,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WHERE pa.attribute = N'dbid' ) AS pa WHERE pa.value IS NOT NULL - AND CONVERT(integer, pa.value) NOT IN (1, 2, 3, 4) + AND (@ignore_system_databases = 0 OR CONVERT(integer, pa.value) NOT IN (1, 2, 3, 4)) AND CONVERT(integer, pa.value) < 32761 AND (@database_id IS NULL OR CONVERT(integer, pa.value) = @database_id) GROUP BY