SQL SERVER 2025 Optional parameter plan optimization (OPPO) What is and benchmarks. Internal part 1 series

Before we dive into today's topic, if you missed my previous post you can take a look at SQL SERVER 2025 CU5 (Cumulative Update 5) Is OUT! A Hot Take on the New Features for DBAs

👉 If you found this deep-dive helpful, feel free to check out the ads—your support helps me keep creating high-quality SQL Server content for the community.

SQL SERVER 2025 Optional Parameter Plan Optimization (OPPO)
What It Is and Benchmarks — Internal Part 1 Series

⚡ SQL Server 2025 finally attacks one of the oldest performance killers: optional parameter queries and unstable execution plans.

🧠 In this post you will learn how OPPO works internally, why it matters for parameter-sensitive workloads, and how to benchmark it yourself with real T-SQL tests.

SQL Server Performance Optimization

🧠 TL;DR BOX

✔️ SQL Server 2025 OPPO automatically creates multiple execution plan variants for optional parameter queries ⚡

✔️ OPPO is part of Intelligent Query Processing and reduces parameter-sensitive plan issues 💣

✔️ Queries using patterns like (@Param IS NULL OR Column = @Param) can now get optimized plans 🚀

✔️ Benchmarks show dramatic improvements in CPU usage, logical reads, and execution stability 🔍

Hi SQL SERVER Guys and Gals,

For more than 20 years, optional parameters have been one of the biggest silent performance killers in SQL Server applications.

The classic pattern:


WHERE Column = @Parameter
OR @Parameter IS NULL

looks innocent.

💣 But internally it creates a nightmare for the optimizer.

SQL Server must generate ONE plan trying to satisfy BOTH scenarios:

  • Highly selective seek queries
  • Large scan queries

That usually means:

  • Bad cardinality estimates
  • Wrong join strategies
  • Excessive memory grants
  • CPU spikes
  • Plan cache instability

🧠 What OPPO Really Is

Optional Parameter Plan Optimization (OPPO) is a new SQL Server 2025 Intelligent Query Processing feature designed to solve parameter-sensitive optional predicates automatically.

⚡ Instead of generating a single compromised execution plan, SQL Server can now generate multiple specialized plans.

This behavior is conceptually similar to Parameter Sensitive Plan (PSP) optimization introduced previously, but focused specifically on optional predicates.

Official Microsoft documentation:

💣 The Old Problem Before OPPO

Consider this classic stored procedure:


CREATE OR ALTER PROCEDURE dbo.SearchOrders
(
    @CustomerID INT = NULL
)
AS
BEGIN

    SELECT
        SalesOrderID,
        CustomerID,
        OrderDate,
        TotalDue
    FROM Sales.SalesOrderHeader
    WHERE CustomerID = @CustomerID
       OR @CustomerID IS NULL;

END
GO

🧠 This query mixes:

  • Selective searches
  • Full table scans

inside the SAME execution plan.

⚡ Result:

  • Bad plan reuse
  • Parameter sniffing instability
  • Huge performance variance

🔍 DIAGNOSIS — Why SQL Server Struggled

Before OPPO, SQL Server had to estimate:

  • How many rows would match
  • Whether to use seek or scan
  • How much memory to allocate

💣 But optional predicates destroy selectivity precision.

One cached plan becomes catastrophic for other executions.

This is one of the most common hidden causes of:

  • CPU pressure
  • Memory grant inflation
  • Random slow queries
  • Execution plan instability

🧪 QUERY — Benchmark Without OPPO

Run this benchmark manually.


-- 🔍 Benchmark Setup

ALTER DATABASE CURRENT
SET COMPATIBILITY_LEVEL = 160;
GO

ALTER DATABASE SCOPED CONFIGURATION 
SET OPTIONAL_PARAMETER_OPTIMIZATION = OFF;
GO

DBCC FREEPROCCACHE;
GO

SET STATISTICS IO, TIME ON;
GO

EXEC dbo.SearchOrders @CustomerID = 11000;
GO

EXEC dbo.SearchOrders @CustomerID = NULL;
GO

⚡ Observe:

  • Logical reads
  • CPU time
  • Plan reuse behavior

💣 Usually one scenario becomes dramatically slower.

🚀 Enabling OPPO

Now enable SQL Server 2025 OPPO.


-- 🚀 Enable OPPO

ALTER DATABASE CURRENT
SET COMPATIBILITY_LEVEL = 170;
GO

ALTER DATABASE SCOPED CONFIGURATION 
SET OPTIONAL_PARAMETER_OPTIMIZATION = ON;
GO

DBCC FREEPROCCACHE;
GO

⚡ Compatibility level 170 is required.

🧪 QUERY — Benchmark WITH OPPO


SET STATISTICS IO, TIME ON;
GO

EXEC dbo.SearchOrders @CustomerID = 11000;
GO

EXEC dbo.SearchOrders @CustomerID = NULL;
GO

🧠 You should now observe:

  • Different plan variants
  • Better cardinality estimates
  • Reduced logical reads
  • Lower CPU usage
  • More stable execution times

⚡ Internal Behavior

Internally, SQL Server now recognizes optional predicates as parameter-sensitive patterns.

Instead of forcing one universal plan, it can create:

  • A seek-oriented plan
  • A scan-oriented plan

🧠 SQL Server dynamically routes execution to the best plan variant depending on runtime parameter values.

This dramatically improves plan quality.

📊 Results Comparison

✅ CL 170 (OPPO Enabled)

Selective Query (CustomerID = 11000)

Logical Reads: 4
CPU: 0 ms
Elapsed Time: 15–20 ms

Full Scan Query (CustomerID = NULL)

Rows Returned: 20164
Logical Reads: 87
CPU: 0 ms
Elapsed Time: 78–79 ms


Execution Plan whit OPPO. Same Query with different paramemeters has different plan! WOW!



💣 CL 160 (OPPO Disabled)

Selective Query (CustomerID = 11000)

Logical Reads: 39
CPU: 0 ms
Elapsed Time: 13–14 ms

Full Scan Query (CustomerID = NULL)

Rows Returned: 20164
Logical Reads: 40365
CPU: 31 ms
Elapsed Time: 88–89 ms



Execution Plan without oppo. We have the same plane if a query has different parameters.



🔥 Key Differences

Metric CL 170 (OPPO) CL 160 Improvement
Logical Reads 87 40365 🔥 ~460x reduction
CPU Time 0 ms 31 ms 💣 Eliminated
Elapsed Time ~79 ms ~89 ms Similar (small dataset)

🧠 Deep Analysis

✅ CL 170 (OPPO Enabled)

  • SQL Server creates multiple execution plans
  • Index Seek used for selective queries
  • Efficient Scan used for full dataset queries
  • Accurate cardinality estimation
  • Minimal logical reads

💣 CL 160 (OPPO Disabled)

  • Single execution plan reused for all scenarios
  • Compromised plan quality
  • Massive unnecessary logical reads
  • Higher CPU usage
  • Poor scalability under load

💣 Important Caveats

OPPO is NOT magic.

There are still scenarios where dynamic SQL or manual query branching is superior.

Examples:

  • Very complex predicates
  • Multi-column optional filters
  • Highly skewed distributions
  • Extreme data volatility

🧠 But for many legacy stored procedures, OPPO is a huge win with zero code changes.

🚀 My REAL Strategy

After 25 years tuning SQL Server systems, here is my practical rule:

⚡ OPPO is one of the biggest real-world optimizer improvements since Parameter Sensitive Plan optimization.

But never blindly trust automation.

My workflow:

  • Enable Query Store first
  • Benchmark before/after
  • Watch memory grants carefully
  • Validate plan stability under concurrency
  • Check plan cache growth

💣 Some workloads improve massively. Others may create additional plan cache pressure.

Always validate under production-like load.

📊 TAKEAWAY

  • ⚡ OPPO solves one of SQL Server's oldest optional parameter optimization problems
  • 🧠 SQL Server 2025 can now generate multiple execution plans automatically
  • 💣 Optional predicates previously caused catastrophic parameter sniffing issues
  • 🚀 OPPO can dramatically reduce CPU, IO, and execution instability
  • 🔍 Benchmarking is mandatory before production rollout

📢 Support the Blog: Did you find this deep-dive helpful? The ads you see here are selected to reflect your interests. If a partner's offer catches your eye, give it a look! Your engagement helps me continue publishing premium SQL Server content for the community.

Biondi Luca @2026 - Sharing over 25 years of Gained Knowledge for Passion. Share if you like my posts!

Comments

I Post più popolari

Speaking to Sql Server, sniffing the TDS protocol

SQL Server, find text in a Trigger, Stored Procedures, View and Function. Two ways and what ways is better

SQL Server, Avoid that damn Table Spool!