Skip to content

Plan analysis: flag an expensive operator no other rule caught (#4527) - #4550

Merged
erikdarlingdata merged 1 commit into
devfrom
plan-sync/4527-expensive-operator
Sep 28, 2026
Merged

erikdarlingdata merged 1 commit into
devfrom
plan-sync/4527-expensive-operator

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Fixes #4527
Part of #4511

Why

Some operators take a large share of a statement's time without tripping any of the plan analyzer's specific rules — a scan that's just reading a lot of data, with no bad estimate, no spill, no missing index to name. Without a catch-all, that time silently disappears from the findings even though it dominated the run.

What changes

  • New rule 35, "Expensive Operator": fires when an operator's own time is at least 20% of the statement's elapsed time, the operator has no other warning already on it, and the statement itself ran at least 1,000ms. Below that floor a percentage share of a few-millisecond statement points at nothing, so short statements are exempt.
  • Severity is Critical at 50% or more self-time, Warning otherwise.
  • The finding's benefit percent is set to the self-time share, mirroring the upstream rule. The benefit-scoring pass isn't wired to recompute this warning type (mirroring the source project, where it also isn't), so that value is carried through as set — it isn't inert due to any gap in this port, it's the same shape as the rule it's ported from.
  • Mirrors erikdarlingdata/PerformanceStudio@e05bc69 (the rule) and erikdarlingdata/PerformanceStudio@0ba9135 / PerformanceStudio#562 (the 1,000ms floor), same message text and severities.
  • Not ported: the source project's "Bare Scan" rule (rule 34) isn't in this codebase yet, so there was no existing OperatorTimeRules list entry to add for rule 35 either — the source project doesn't add "Expensive Operator" to that list, so this port doesn't either.

Test plan

New file Darling/Darling.Tests/PlanSync4527Tests.cs, five cases against a synthetic single-leaf-operator plan (dbo.T, [db]), all through ShowPlanParser.Parse + PlanAnalyzer.Analyze:

CHANGELOG

SECTION: Added
ENTRY: - Plan analysis now flags an operator that takes a large share of a statement's run time even when no other rule has advice for it ([#4550]) - A new "Expensive Operator" finding fires when a single operator's own time is at least 20% of a statement that ran 1 second or longer, so a big chunk of runtime no longer disappears from the findings just because nothing specific was wrong with it.
REF: [#4550]: #4550

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant