Skip to content

Estimated Plan CE Guess (rule 33) names the wrong predicate for most default guesses and ignores the CE model version #4687

Description

@erikdarlingdata

A plan analysis fix from PerformanceStudio (PS) that PerformanceMonitor (PM) still needs. It comes from PS PR #608, which merged after the PS-to-PM sync in #4511 was finished.

Summary

Rule 33 (PlanAnalyzer.cs:1223) looks at scans on tables of 100,000 rows or more. It warns when the estimate matches one of the optimizer's fixed guesses. DetectCeGuess (PlanAnalyzer.cs:2998) picks the label for the warning. Three of its five labels name the wrong predicate. The other two are incomplete or wrong for some CE versions.

Estimate PM label today What produces it
30% equality guess An inequality such as a > 5, in every CE version.
10% inequality guess One column compared with another, in every CE version. From CE 130, also an equality on an expression such as ABS(a) = 5.
9% LIKE/BETWEEN guess BETWEEN or a two-sided range. From CE 120, also LIKE. Under CE 70, also two inequalities on different columns.
16.4% compound predicate guess From CE 120 only: two inequalities on different columns, or a range on variables or on an expression. Under CE 70 the same predicates give 9%.
1% multi-inequality guess Under CE 70 only: two 10% guesses multiplied, for example a = b AND c = d. No inequality gives 1%. CE 120 and later give 3.16% for those predicates.

DetectCeGuess also never checks for the equality guess, and it never sees the CE version. So PM can report a band that the plan's estimator does not have.

PerformanceStudio

erikdarlingdata/PerformanceStudio@1964013 (erikdarlingdata/PerformanceStudio#608) rewrites DetectCeGuess after PS measured each guess again. The measurements ran on SQL Server 2025 on a 100,000-row heap with no statistics. CE 70 used FORCE_LEGACY_CARDINALITY_ESTIMATION, and CE 120 to 170 used the compatibility level. The PS pull request lists the row counts for each predicate.

The new DetectCeGuess differs from PM's in four ways:

  • It takes the statement's CardinalityEstimationModelVersion. A band that the estimator does not have is not reported. A plan with no version can match any band.
  • Its labels follow the "What produces it" column above.
  • It detects the equality guess, which depends on the row count. The guess is the square root of the row count from CE 120, and the row count to the power 0.75 under CE 70. The match tolerance is 1%.
  • The 100,000-row minimum is a named constant, CeGuessMinTableRows, with a comment that says why. If the table is smaller, the equality guess lands on the fixed bands. At 100,000 rows it is 0.3% (CE 120 and later) or 5.6% (CE 70), and it falls as the table grows.

An equality estimate from real statistics can also land within 1% of the square root of the row count. The warning text already says that the optimizer "may be using" a default guess.

Port

Replace DetectCeGuess (PlanAnalyzer.cs:2998 to 3013) with the PS version. Pass stmt.CardinalityEstimationModelVersion at the call site (PlanAnalyzer.cs:1230). The variable stmt is already in scope there, and PM already parses the CE version (ShowPlanParser.cs:599 and 667).

PM already has the 100,000-row minimum, as the literal 100_000 at PlanAnalyzer.cs:1224. The equality check depends on it, so it must stay. We recommend the named constant and the comment from PS, because the next reader must know why that number matters. Update the comment at PlanAnalyzer.cs:1219 to 1222, which repeats the old labels.

The rule number and the warning type ("Estimated Plan CE Guess") do not change. No PM test names the old labels. The PS tests are in CeGuessDetectionTests (tests/PlanViewer.Core.Tests). Every estimate in them is a value that SQL Server wrote in the PS measurements. Size S.

At 4c6dfe10. dev has no later change to PerformanceMonitor.PlanAnalysis.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions