From 04ccefc7a6a1b082a7acedf7c0f07e7d732bbf27 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:43:11 -0400 Subject: [PATCH 1/6] Add "Powered by Performance Studio" line on landing page Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Web/Pages/Index.razor | 1 + src/PlanViewer.Web/wwwroot/css/app.css | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/PlanViewer.Web/Pages/Index.razor b/src/PlanViewer.Web/Pages/Index.razor index 6aae734..3e9be24 100644 --- a/src/PlanViewer.Web/Pages/Index.razor +++ b/src/PlanViewer.Web/Pages/Index.razor @@ -6,6 +6,7 @@

Free SQL Server Query Plan Analysis

Paste or upload a .sqlplan file. Your plan XML never leaves your browser.

+

Powered by the same analysis engine in the Performance Studio app.

@if (errorMessage != null) { diff --git a/src/PlanViewer.Web/wwwroot/css/app.css b/src/PlanViewer.Web/wwwroot/css/app.css index 95b0cb4..88fc17a 100644 --- a/src/PlanViewer.Web/wwwroot/css/app.css +++ b/src/PlanViewer.Web/wwwroot/css/app.css @@ -168,9 +168,25 @@ main { font-family: 'Montserrat', sans-serif; font-size: 1.05rem; font-weight: 600; + margin-bottom: 0.4rem; +} + +.powered-by { + color: var(--text-secondary); + font-size: 0.9rem; margin-bottom: 1.5rem; } +.powered-by a { + color: var(--accent); + text-decoration: none; + font-weight: 600; +} + +.powered-by a:hover { + text-decoration: underline; +} + /* === Input Area === */ .input-area { text-align: left; From 6c6c1f0e31035f6b3d755e8c9480c485a3fa22f6 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:58:12 -0400 Subject: [PATCH 2/6] Add Darling Data favicon to web app Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Web/wwwroot/favicon.png | Bin 0 -> 39737 bytes src/PlanViewer.Web/wwwroot/index.html | 1 + 2 files changed, 1 insertion(+) create mode 100644 src/PlanViewer.Web/wwwroot/favicon.png diff --git a/src/PlanViewer.Web/wwwroot/favicon.png b/src/PlanViewer.Web/wwwroot/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..9c6db66abf67f052aaa496cf675178c8712ea1a6 GIT binary patch literal 39737 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 literal 0 HcmV?d00001 diff --git a/src/PlanViewer.Web/wwwroot/index.html b/src/PlanViewer.Web/wwwroot/index.html index 543dff4..04ba38d 100644 --- a/src/PlanViewer.Web/wwwroot/index.html +++ b/src/PlanViewer.Web/wwwroot/index.html @@ -4,6 +4,7 @@ Free SQL Server Query Plan Analysis — Darling Data + From 4453034c5ee19adc1fc32351b9ba478dc912a6a1 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:03:01 -0400 Subject: [PATCH 3/6] Add Open Graph and Twitter Card meta tags for social sharing Uses the Darling Data barbell logo as hero image when shared on social media. Also adds meta description for SEO. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Web/wwwroot/index.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/PlanViewer.Web/wwwroot/index.html b/src/PlanViewer.Web/wwwroot/index.html index 04ba38d..432cfe7 100644 --- a/src/PlanViewer.Web/wwwroot/index.html +++ b/src/PlanViewer.Web/wwwroot/index.html @@ -4,6 +4,16 @@ Free SQL Server Query Plan Analysis — Darling Data + + + + + + + + + + From ba2beeb03c7861942d23702eb27bb6c2f9b4562d Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:09:49 -0400 Subject: [PATCH 4/6] Clarify OG description: in-browser, nothing to install Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Web/wwwroot/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PlanViewer.Web/wwwroot/index.html b/src/PlanViewer.Web/wwwroot/index.html index 432cfe7..ebfd4ee 100644 --- a/src/PlanViewer.Web/wwwroot/index.html +++ b/src/PlanViewer.Web/wwwroot/index.html @@ -6,13 +6,13 @@ Free SQL Server Query Plan Analysis — Darling Data - + - + From 68ff836d372a3b7c73b27530c6fa7e0096a21daf Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:26:43 -0400 Subject: [PATCH 5/6] Fix Rule 3 severity: CouldNotGenerateValidParallelPlan is actionable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reason means something in the query blocks parallelism (scalar UDFs, table variable inserts, etc.) — that's worth a Warning, not Info. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Core/Services/PlanAnalyzer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/PlanViewer.Core/Services/PlanAnalyzer.cs b/src/PlanViewer.Core/Services/PlanAnalyzer.cs index d89458d..af6a5a3 100644 --- a/src/PlanViewer.Core/Services/PlanAnalyzer.cs +++ b/src/PlanViewer.Core/Services/PlanAnalyzer.cs @@ -141,14 +141,16 @@ private static void AnalyzeStatement(PlanStatement stmt, AnalyzerConfig cfg) _ => stmt.NonParallelPlanReason }; - // Only warn (not info) when the user explicitly forced serial execution - var isExplicit = stmt.NonParallelPlanReason is "MaxDOPSetToOne" or "QueryHintNoParallelSet"; + // Warn when the user forced serial or something in the query blocks parallelism. + // Info only for passive reasons (cost below threshold, edition limitation). + var isActionable = stmt.NonParallelPlanReason is "MaxDOPSetToOne" + or "QueryHintNoParallelSet" or "CouldNotGenerateValidParallelPlan"; stmt.PlanWarnings.Add(new PlanWarning { WarningType = "Serial Plan", Message = $"Query running serially: {reason}.", - Severity = isExplicit ? PlanWarningSeverity.Warning : PlanWarningSeverity.Info + Severity = isActionable ? PlanWarningSeverity.Warning : PlanWarningSeverity.Info }); } From 56150212e7f8f9ada43aef13bbc488e65339ed09 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:31:31 -0400 Subject: [PATCH 6/6] Expand Rule 3 to cover all NonParallelPlanReason values Adds human-readable messages for all 25 known reasons. Severity: - Warning: actionable reasons (UDFs, cursors, table variables, remote queries, trace flags, hints, DML OUTPUT, writeback variables) - Info: passive/environmental (cost below threshold, edition limits, memory-optimized tables, upgrade mode, index build edge cases) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.Core/Services/PlanAnalyzer.cs | 58 ++++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/PlanViewer.Core/Services/PlanAnalyzer.cs b/src/PlanViewer.Core/Services/PlanAnalyzer.cs index af6a5a3..c2b2fe6 100644 --- a/src/PlanViewer.Core/Services/PlanAnalyzer.cs +++ b/src/PlanViewer.Core/Services/PlanAnalyzer.cs @@ -133,18 +133,66 @@ private static void AnalyzeStatement(PlanStatement stmt, AnalyzerConfig cfg) { var reason = stmt.NonParallelPlanReason switch { + // User/config forced serial "MaxDOPSetToOne" => "MAXDOP is set to 1", + "QueryHintNoParallelSet" => "OPTION (MAXDOP 1) hint forces serial execution", + "ParallelismDisabledByTraceFlag" => "Parallelism disabled by trace flag", + + // Passive — optimizer chose serial, nothing wrong "EstimatedDOPIsOne" => "Estimated DOP is 1 (the plan's estimated cost was below the cost threshold for parallelism)", + + // Edition/environment limitations "NoParallelPlansInDesktopOrExpressEdition" => "Express/Desktop edition does not support parallelism", + "NoParallelCreateIndexInNonEnterpriseEdition" => "Parallel index creation requires Enterprise edition", + "NoParallelPlansDuringUpgrade" => "Parallel plans disabled during upgrade", + "NoParallelForPDWCompilation" => "Parallel plans not supported for PDW compilation", + "NoParallelForCloudDBReplication" => "Parallel plans not supported during cloud DB replication", + + // Query constructs that block parallelism (actionable) "CouldNotGenerateValidParallelPlan" => "Optimizer could not generate a valid parallel plan. Common causes: scalar UDFs, inserts into table variables, certain system functions, or OPTION (MAXDOP 1) hints", - "QueryHintNoParallelSet" => "OPTION (MAXDOP 1) hint forces serial execution", + "TSQLUserDefinedFunctionsNotParallelizable" => "T-SQL scalar UDF prevents parallelism. Rewrite as an inline table-valued function, or on SQL Server 2019+ check if the UDF is eligible for automatic inlining", + "CLRUserDefinedFunctionRequiresDataAccess" => "CLR UDF with data access prevents parallelism", + "NonParallelizableIntrinsicFunction" => "Non-parallelizable intrinsic function in the query", + "TableVariableTransactionsDoNotSupportParallelNestedTransaction" => "Table variable transaction prevents parallelism. Consider using a #temp table instead", + "UpdatingWritebackVariable" => "Updating a writeback variable prevents parallelism", + "DMLQueryReturnsOutputToClient" => "DML with OUTPUT clause returning results to client prevents parallelism", + "MixedSerialAndParallelOnlineIndexBuildNotSupported" => "Mixed serial/parallel online index build not supported", + "NoRangesResumableCreate" => "Resumable index create cannot use parallelism for this operation", + + // Cursor limitations + "NoParallelCursorFetchByBookmark" => "Cursor fetch by bookmark cannot use parallelism", + "NoParallelDynamicCursor" => "Dynamic cursors cannot use parallelism", + "NoParallelFastForwardCursor" => "Fast-forward cursors cannot use parallelism", + + // Memory-optimized / natively compiled + "NoParallelForMemoryOptimizedTables" => "Memory-optimized tables do not support parallel plans", + "NoParallelForDmlOnMemoryOptimizedTable" => "DML on memory-optimized tables cannot use parallelism", + "NoParallelForNativelyCompiledModule" => "Natively compiled modules do not support parallelism", + + // Remote queries + "NoParallelWithRemoteQuery" => "Remote queries cannot use parallelism", + "NoRemoteParallelismForMatrix" => "Remote parallelism not available for this query shape", + _ => stmt.NonParallelPlanReason }; - // Warn when the user forced serial or something in the query blocks parallelism. - // Info only for passive reasons (cost below threshold, edition limitation). - var isActionable = stmt.NonParallelPlanReason is "MaxDOPSetToOne" - or "QueryHintNoParallelSet" or "CouldNotGenerateValidParallelPlan"; + // Actionable: user forced serial, or something in the query blocks parallelism + // that could potentially be rewritten. Info: passive (cost too low) or + // environmental (edition, upgrade, cursor type, memory-optimized). + var isActionable = stmt.NonParallelPlanReason is + "MaxDOPSetToOne" or "QueryHintNoParallelSet" or "ParallelismDisabledByTraceFlag" + or "CouldNotGenerateValidParallelPlan" + or "TSQLUserDefinedFunctionsNotParallelizable" + or "CLRUserDefinedFunctionRequiresDataAccess" + or "NonParallelizableIntrinsicFunction" + or "TableVariableTransactionsDoNotSupportParallelNestedTransaction" + or "UpdatingWritebackVariable" + or "DMLQueryReturnsOutputToClient" + or "NoParallelCursorFetchByBookmark" + or "NoParallelDynamicCursor" + or "NoParallelFastForwardCursor" + or "NoParallelWithRemoteQuery" + or "NoRemoteParallelismForMatrix"; stmt.PlanWarnings.Add(new PlanWarning {