Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Python | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Python | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA | Python |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA | Python
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Databricks | Power Apps | Power Automate |
Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables | Power Apps | Power Automate
Power BI | Power Apps | Power Automate | SQL | VBA | Python | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables
Power BI | Power Apps | Power Automate | SQL | VBA | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
Parameter sniffing is still one of the most common causes of unstable query performance in MS-SQL 2026. In this article you'll see how to detect real parameter sniffing problems, then choose the right fix: RECOMPILE, OPTIMIZE FOR, or plan guides.
If you’re using SQL as the backbone for Power BI models or other reporting tools, understanding parameter sniffing is key to keeping refreshes predictable; it pairs nicely with building robust SQL-based models using something like a Power BI with SQL deep-dive.
When a parameterized query or stored procedure runs the first time, SQL Server uses the actual parameter values to estimate row counts, choose indexes, and build an execution plan. That plan is cached and reused for later executions.
Parameter sniffing problems occur when:
This is not always bad. Most of the time, parameter sniffing is beneficial. You only need to act when:
If Query Store is enabled (it should be on any serious 2026 instance), it’s your best starting point.
SELECT TOP 50
qsq.query_id,
qsqt.query_sql_text,
SUM(rs.avg_duration * rs.count_executions) AS total_duration,
COUNT(DISTINCT rs.plan_id) AS plan_count
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id = qsp.query_id
JOIN sys.query_store_runtime_stats rs
ON qsp.plan_id = rs.plan_id
GROUP BY qsq.query_id, qsqt.query_sql_text
ORDER BY total_duration DESC;
plan_count > 1) and large variation in avg_duration between plans.query_id, drill into runtime stats by parameter values.Parameter sniffing suspects usually show:
Run the same stored procedure or query twice with different parameter values and capture actual execution plans.
Example:
-- Example proc
CREATE OR ALTER PROC dbo.GetOrders
@CustomerId INT
AS
BEGIN
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId;
END;
GO
-- Execution 1: rare customer
EXEC dbo.GetOrders @CustomerId = 999999; -- very few rows
-- Execution 2: heavy customer
EXEC dbo.GetOrders @CustomerId = 42; -- many rows
Symptoms of parameter sniffing:
In the execution plan, compare:
If estimates are consistently off by orders of magnitude only for certain parameter values, that’s a strong sign.
Once you confirm parameter sniffing, you have three main knobs:
RECOMPILE (per query or per execution)OPTIMIZE FOR hintsEach has a specific sweet spot and trade-offs.
RECOMPILE forces SQL Server to build a new plan for each execution of the statement or procedure, using the current parameter values.
You can apply it:
At statement level:
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId
OPTION (RECOMPILE);
At procedure level:
CREATE OR ALTER PROC dbo.GetOrders
@CustomerId INT
WITH RECOMPILE
AS
BEGIN
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId;
END;
Use RECOMPILE when:
Avoid it on:
OPTIMIZE FOR tells the optimizer which parameter value to use when estimating, regardless of the actual runtime value.
Optimize for a specific value:
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId
OPTION (OPTIMIZE FOR (@CustomerId = 42));
Optimize for UNKNOWN (use average density instead of sniffed value):
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId
OPTION (OPTIMIZE FOR UNKNOWN);
You can use these hints inside stored procedures by adding them to individual statements.
RECOMPILE in high-frequency workloads.Use OPTIMIZE FOR when:
OPTIMIZE FOR UNKNOWN is handy when:
Plan guides let you attach hints (like OPTIMIZE FOR or RECOMPILE) to queries without changing the source. Useful for:
Assume the vendor proc runs this query (simplified):
SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId;
You can attach a plan guide with OPTIMIZE FOR UNKNOWN:
EXEC sp_create_plan_guide
@name = N'Guide_Orders_OptimizeForUnknown',
@stmt = N'SELECT o.OrderID, o.OrderDate, o.Amount
FROM dbo.Orders o
WHERE o.CustomerId = @CustomerId;',
@type = N'SQL',
@module_or_batch = NULL,
@params = N'@CustomerId INT',
@hints = N'OPTION (OPTIMIZE FOR UNKNOWN)';
Key points:
@stmt must match the query text exactly as SQL Server sees it (whitespace and formatting matter).sys.fn_get_sql or Query Store to copy the exact text when possible.Use plan guides when:
OPTIMIZE FOR, RECOMPILE, or even index hints) for a known problematic query.Prefer code changes over plan guides whenever you can change the code.
When you’ve confirmed parameter sniffing, walk through these decision points.
OPTION (RECOMPILE) is usually safe and simple.RECOMPILE unless CPU is abundant.OPTIMIZE FOR or OPTIMIZE FOR UNKNOWN.Highly skewed, and different plans are really needed for different ranges:
RECOMPILE.IF @CustomerId < 1000
BEGIN
-- Path 1: small customers
SELECT ...
OPTION (OPTIMIZE FOR (@CustomerId = 10));
END
ELSE
BEGIN
-- Path 2: big customers
SELECT ...
OPTION (OPTIMIZE FOR (@CustomerId = 50000));
END
Moderately skewed:
OPTIMIZE FOR with a carefully chosen typical value.OPTIMIZE FOR UNKNOWN if you want a generic plan.OPTION (RECOMPILE) or a temporary plan guide.OPTIMIZE FOR or code changes.You can turn this into a repeatable playbook:
Identify the query
Reproduce with different parameters
Confirm sniffing
Pick the least invasive fix
OPTIMIZE FOR or RECOMPILE.Monitor after the change
Don’t try to “turn off” parameter sniffing globally; it’s usually helping you. Use Query Store to find the handful of queries where sniffing hurts, then choose the smallest, most targeted fix: RECOMPILE for rare, heavy hitters, OPTIMIZE FOR for stable workhorses, and plan guides only when you can’t touch the code.
MS-SQL
New
Next Batches Now Live
Power BI
SQL
Power Apps
Power Automate
Microsoft Fabrics
Azure Data Engineering