diff --git a/Dashboard/Services/PlanAnalyzer.cs b/Dashboard/Services/PlanAnalyzer.cs index 5c9e8c9f..4c2e59b6 100644 --- a/Dashboard/Services/PlanAnalyzer.cs +++ b/Dashboard/Services/PlanAnalyzer.cs @@ -38,9 +38,12 @@ public static void Analyze(ParsedPlan plan) private static void AnalyzeStatement(PlanStatement stmt) { // Rule 3: Serial plan with reason - // Skip trivial statements (e.g., variable assignments, constant scans) — not worth warning about + // Skip: trivial cost (< 0.01), TRIVIAL optimization (can't go parallel anyway), + // and 0ms actual elapsed time (not worth flagging). if (!string.IsNullOrEmpty(stmt.NonParallelPlanReason) - && stmt.StatementSubTreeCost >= 0.01) + && stmt.StatementSubTreeCost >= 0.01 + && stmt.StatementOptmLevel != "TRIVIAL" + && !(stmt.QueryTimeStats != null && stmt.QueryTimeStats.ElapsedTimeMs == 0)) { var reason = stmt.NonParallelPlanReason switch { @@ -52,11 +55,13 @@ private static void AnalyzeStatement(PlanStatement stmt) _ => stmt.NonParallelPlanReason }; + var isExplicit = stmt.NonParallelPlanReason is "MaxDOPSetToOne" or "QueryHintNoParallelSet"; + stmt.PlanWarnings.Add(new PlanWarning { WarningType = "Serial Plan", Message = $"Query running serially: {reason}.", - Severity = PlanWarningSeverity.Warning + Severity = isExplicit ? PlanWarningSeverity.Warning : PlanWarningSeverity.Info }); } diff --git a/Lite/Services/PlanAnalyzer.cs b/Lite/Services/PlanAnalyzer.cs index 8308aafc..7f944295 100644 --- a/Lite/Services/PlanAnalyzer.cs +++ b/Lite/Services/PlanAnalyzer.cs @@ -38,9 +38,12 @@ public static void Analyze(ParsedPlan plan) private static void AnalyzeStatement(PlanStatement stmt) { // Rule 3: Serial plan with reason - // Skip trivial statements (e.g., variable assignments, constant scans) — not worth warning about + // Skip: trivial cost (< 0.01), TRIVIAL optimization (can't go parallel anyway), + // and 0ms actual elapsed time (not worth flagging). if (!string.IsNullOrEmpty(stmt.NonParallelPlanReason) - && stmt.StatementSubTreeCost >= 0.01) + && stmt.StatementSubTreeCost >= 0.01 + && stmt.StatementOptmLevel != "TRIVIAL" + && !(stmt.QueryTimeStats != null && stmt.QueryTimeStats.ElapsedTimeMs == 0)) { var reason = stmt.NonParallelPlanReason switch { @@ -52,11 +55,13 @@ private static void AnalyzeStatement(PlanStatement stmt) _ => stmt.NonParallelPlanReason }; + var isExplicit = stmt.NonParallelPlanReason is "MaxDOPSetToOne" or "QueryHintNoParallelSet"; + stmt.PlanWarnings.Add(new PlanWarning { WarningType = "Serial Plan", Message = $"Query running serially: {reason}.", - Severity = PlanWarningSeverity.Warning + Severity = isExplicit ? PlanWarningSeverity.Warning : PlanWarningSeverity.Info }); }