Skip to content

Fix the plan shape described for the optional parameter pattern - #10492

Open
Rudi Bruchez (rudi-bruchez) wants to merge 1 commit into
MicrosoftDocs:livefrom
rudi-bruchez:fix/oppo-index-scan
Open

Rudi Bruchez (rudi-bruchez) wants to merge 1 commit into
MicrosoftDocs:livefrom
rudi-bruchez:fix/oppo-index-scan

Conversation

@rudi-bruchez

Copy link
Copy Markdown
Contributor

What's wrong

In "Supported query patterns", the page says the optimizer can't seek on the index on the bedrooms column because a seek isn't valid when @bedrooms is NULL, then ends with:

The generated plan doesn't include a scan of the index.

Without OPPO, the generated plan does scan that index, which is what the previous sentence leads to.

Evidence

SQL Server 2025 CU10 (17.0.5035.5), Developer edition, Linux container. Fresh database, 200,000 rows, nonclustered index on bedrooms.

CREATE TABLE dbo.Properties (id int IDENTITY PRIMARY KEY, bedrooms int NOT NULL, price int NOT NULL, descr char(200) NOT NULL DEFAULT 'x');
INSERT dbo.Properties (bedrooms, price)
SELECT TOP (200000) CASE WHEN n % 20000 = 0 THEN 10 ELSE n % 6 END, n % 1000
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) n FROM sys.all_columns a CROSS JOIN sys.all_columns b) t;
CREATE INDEX ix_bedrooms ON dbo.Properties (bedrooms);
GO
CREATE PROCEDURE dbo.p_star @bedrooms int AS
SELECT * FROM dbo.Properties WHERE bedrooms = @bedrooms OR @bedrooms IS NULL;
GO
ALTER DATABASE SCOPED CONFIGURATION SET OPTIONAL_PARAMETER_OPTIMIZATION = OFF;
EXEC dbo.p_star 10;

Observed with OPPO off at compatibility level 170, and at levels 160 and 150 where OPPO doesn't apply: one plan for both parameter values, Nested Loops over an Index Scan of ix_bedrooms with a Clustered Index Seek (a covering SELECT id, bedrooms gives an Index Scan of ix_bedrooms alone). With OPPO on at level 170: two variants, an Index Seek of ix_bedrooms for @bedrooms = 10 and a scan for NULL, as the rest of the page describes.

Expected per the current text: no scan of the index.

Change

"doesn't include" becomes "includes" in that sentence.

Without optional parameter plan optimization, a query of the form
col = @p OR @p IS NULL compiles to a plan that scans the index on col,
since a seek isn't valid when the parameter is NULL. The sentence said
the plan doesn't include a scan, which contradicts the sentence before it.
@prmerger-automator

Copy link
Copy Markdown
Contributor

Rudi Bruchez (@rudi-bruchez) : Thanks for your contribution! The author(s) and reviewer(s) have been notified to review your proposed change.

@prmerger-automator

Copy link
Copy Markdown
Contributor

Rudi Bruchez (@rudi-bruchez) : Thanks for your contribution! The author(s) and reviewer(s) have been notified to review your proposed change.

@learn-build-service-prod

Copy link
Copy Markdown
Contributor

Learn Build status updates of commit 3165082:

✅ Validation status: passed

File Status Preview URL Details
docs/relational-databases/performance/optional-parameter-optimization.md ✅Succeeded

For more details, please refer to the build report.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants