SQL Server 2025 Series : Degree Of Parallelism (DOP) Feedback Explained with Real-Time Demo!

Parallelism tuning has always been one of the most challenging aspects of SQL Server performance optimization. DBAs often spend hours fine-tuning MAXDOP settings, trying to strike the perfect balance between performance and resource consumption.

With SQL Server 2025, this challenge is significantly reduced thanks to Degree of Parallelism (DOP) Feedbackβ€”a powerful Intelligent Query Processing feature that automatically optimizes parallel query execution.

In this blog, we will walk through:

  • What DOP Feedback is
  • How to track it using Extended Events
  • A real-time demo with multiple scenarios
  • How to validate whether DOP Feedback is working on your server

What is DOP Feedback?

DOP Feedback enables SQL Server to self-adjust the degree of parallelism for repeated queries. Instead of relying on static MAXDOP settings, SQL Server analyzes runtime performance (CPU usage, execution time, waits) and dynamically tunes DOP for subsequent executions.

This helps:

  • Reduce excessive CPU usage
  • Improve query performance
  • Eliminate manual tuning effort

Tracking DOP Feedback using Extended Events

To understand how SQL Server applies DOP Feedback, we can capture internal engine decisions using Extended Events.

Setup DOP Feedback Tracking

IF EXISTS (SELECT 1 FROM sys.server_event_sessions WHERE name = 'DOPFeedbackWatch')
DROP EVENT SESSION DOPFeedbackWatch ON SERVER;
GO
CREATE EVENT SESSION DOPFeedbackWatch ON SERVER
ADD EVENT sqlserver.dop_feedback_eligible_query(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_provided(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_validation(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_stabilized(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_reverted(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_analysis_stopped(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash)),
ADD EVENT sqlserver.dop_feedback_reassessment_failed(
ACTION(sqlserver.sql_text, sqlserver.plan_handle, sqlserver.query_hash))
ADD TARGET package0.ring_buffer;
GO
ALTER EVENT SESSION DOPFeedbackWatch ON SERVER STATE = START;
GO

What this captures

This session helps us track:

  • When a query becomes eligible for DOP Feedback
  • When SQL Server adjusts DOP
  • Whether feedback is validated or reverted
  • When the system stabilizes on an optimal DOP

This gives real-time visibility into the self-tuning engine behavior.


DOP Feedback Demo (Step-by-Step)

Let’s simulate workloads to observe DOP Feedback in action.


Scenario 1: High-Volume Parallel Query (Feedback Adjusted)

CREATE DATABASE jbdb
GO
USE JBDB
GO
--Create table and load table
CREATE TABLE [dbo].[Table1]([Col1] [int] IDENTITY(1,1) ON [PRIMARY]
GO
set nocount on
insert into Table1 (Col2, Col3, Col4, Col5) values (1, REPLICATE ('a',4000), 10, 100)
go 999
insert into Table1 (Col2, Col3, Col4, Col5) values (2, REPLICATE ('z',4000), 11, 100)
go 99999
insert into Table1 (Col2, Col3, Col4, Col5) values (3, REPLICATE ('f',4000), 12, 100)
go 8965
insert into Table1 (Col2, Col3, Col4, Col5) values (4, REPLICATE ('g',4000), 13, 100)
go 7844
insert into Table1 (Col2, Col3, Col4, Col5) values (5, REPLICATE ('u',4000), 14, 100)
go 4567
insert into Table1 (Col2, Col3, Col4, Col5) values (2, REPLICATE ('z',4000), 11, 100)
go 751049
-- Stored Procedure to query the table
CREATE OR ALTER PROCEDURE [dbo].[usp_GetDetails] @Col2 int
AS
BEGIN
SELECT top (50000)
[Col1],
[Col2],
[Col3],
[Col4],
[Col5]
FROM dbo.Table1
WHERE [Col2] = @Col2
ORDER BY [Col3];
END
--EXECUTE the stored procedure
EXEC [dbo].[usp_GetDetails] @Col2 = 2
--OSTRESS
C:\Program Files\Microsoft Corporation\RMLUtils>ostress -S"VIJANAK\IN2025" -E -Q"EXEC usp_GetDetails @Col2 = 2;" -n1 -r100 -q -dJBDB

In this scenario:

  • Query executes repeatedly under load
  • SQL Server identifies inefficiencies in parallelism
  • DOP is adjusted for better performance

Scenario 2: Skewed Parallelism (Feedback Evaluation)

use JBBlog
[dbo].[usp_SkewedParallelReport]
ostress -S"VIJANAK\IN2025" -E -Q"EXEC usp_SkewedParallelReport;" -n1 -r100 -q -dJBBlog

Here:

  • SQL Server evaluates skewed workloads
  • Determines whether reducing DOP improves efficiency
  • May validate or reject feedback

Monitoring Live Workload

To see what is actively running:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- What SQL Statements Are Currently Running?
SELECT [Spid] = session_Id
, ecid
, [Database] = DB_NAME(sp.dbid)
, [User] = nt_username
, [Status] = er.status
, [Wait] = wait_type
, [Individual Query] = SUBSTRING (qt.text,
er.statement_start_offset/2,
(CASE WHEN er.statement_end_offset = -1
THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
ELSE er.statement_end_offset END -
er.statement_start_offset)/2)
,[Parent Query] = qt.text
, Program = program_name
, Hostname
, nt_domain
, start_time
FROM sys.dm_exec_requests er
INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle)as qt
where session_Id NOT IN (@@SPID) -- Ignore this current statement.
ORDER BY 1, 2
go

This helps you:

  • Identify active queries
  • Validate parallel workloads
  • Correlate with Extended Event output

Key Observations from the Demo

From the above scenarios, you will typically notice:

  1. DOP Feedback Applied Successfully
    • SQL Server reduces or adjusts DOP
    • Performance improves over repeated executions
  2. Optimal DOP Identified
    • No change needed
    • System confirms current DOP is efficient
  3. Query Not Eligible
    • Some queries are excluded
    • Depends on execution pattern and workload

Why This Matters

DOP Feedback fundamentally changes how DBAs approach tuning:

Traditional ApproachSQL Server 2025 Approach
Manual MAXDOP tuningAutomatic per-query tuning
Trial and errorData-driven decisions
Static configurationAdaptive optimization

Watch the Full Demo

I’ve recorded a complete walkthrough of this setup on my YouTube channel JBSWiki. If you’re a visual learner, go check it out!

πŸ‘‰ Watch here: https://www.youtube.com/watch?v=nVMeQeiUKTA


Final Thoughts

With SQL Server 2025, the database engine becomes smarter and more autonomous.

DOP Feedback:

  • Eliminates guesswork
  • Improves performance stability
  • Reduces CPU contention
  • Adapts dynamically to workload changes

For DBAs and performance engineers, this means less time tuning and more time delivering value.


If you are testing SQL Server 2025 in your environment, I highly recommend running this demo and observing the Extended Events output β€” it gives incredible insight into how the engine learns and adapts in real time.

Thank You,
Vivek Janakiraman

Disclaimer:
The views expressed on this blog are mine alone and do not reflect the views of my company or anyone else. All postings on this blog are provided β€œAS IS” with no warranties, and confers no rights.

SQL Server Cleanup Using UninstallString When Programs and Features Entry is Missing

Issue

In some environments, SQL Server services may still exist on the server, but the related SQL Server entries are missing from Programs and Features. This can happen due to missing or corrupted registry entries, incomplete uninstallations, or failed patching activities.

To identify the uninstall information from the registry, the following PowerShell script can be used:

Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, `
HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object { $_.DisplayName -like “*SQL Server 2016*” } |
Select-Object DisplayName, UninstallString

Solution

The above script helps retrieve the UninstallString for SQL Server components directly from the registry.

In many cases, the uninstall command may contain:

/I

For uninstallation, this should be replaced with:

/X

Example:

MsiExec.exe /x

This forces the uninstall operation instead of launching the installer in maintenance mode.


Important Remarks

  • This approach should mainly be considered for remote support cases or emergency cleanup situations.
  • There is always a possibility of future issues when manually cleaning up SQL Server components using registry-based uninstall methods.
  • The recommended and safest approach is always to rebuild the server if SQL Server installation metadata or registry entries are heavily corrupted.
  • Use this method only as a last resort and proceed at your own risk.

Summary

When SQL Server entries are missing from Programs and Features, the uninstall details can still be retrieved from the Windows registry using PowerShell. Replacing /I with /X in the uninstall command can help remove orphaned SQL Server components. However, since this method relies on registry-based cleanup, it should only be used cautiously in exceptional scenarios, with server rebuild remaining the preferred long-term solution.

Thank You,
Vivek Janakiraman

Disclaimer:
The views expressed on this blog are mine alone and do not reflect the views of my company or anyone else. All postings on this blog are provided β€œAS IS” with no warranties, and confers no rights.

Securely Scheduling Index Maintenance on Azure SQL Database Using Automation Account & Managed Identity

Index maintenance is a critical task for optimizing database performance, ensuring queries run efficiently, and keeping Azure SQL Database in top shape. Traditionally, scheduling index maintenance required storing credentials in scripts, posing security risks. However, in this blog, we’ll walk through a secure way to automate index maintenance using Azure Automation Account, Managed Identity, and PowerShell, ensuring no explicit credentials are stored. πŸ”’

Check out the video in you tube for a hand on experience.

βœ… Why Automate Index Maintenance?

  • Enhances query performance by reducing fragmentation.
  • Ensures index optimization without manual intervention.
  • Uses Managed Identity for secure authentication, avoiding stored credentials.
  • Fully automated scheduling with Azure Automation Account.

πŸ—οΈ Prerequisites

Before we begin, ensure you have the following:

  • An Azure SQL Database instance.
  • An Azure Automation Account.
  • The Ola Hallengren IndexOptimize stored procedure installed on your database.
  • PowerShell Az module installed in the Automation Account.

🎯 Step 1: Create a Managed Identity for the Automation Account

To allow your Automation Account to securely authenticate against Azure SQL Database, assign it a System-Assigned Managed Identity:

  1. Navigate to Azure Portal β†’ Automation Accounts.
  2. Select your Automation Account.
  3. Under Identity, enable System Assigned Managed Identity.
  4. Copy the Object ID; we’ll need it in the next step.

πŸ”‘ Step 2: Grant Database Access to the Managed Identity

Now, we need to create a login and database user in Azure SQL Database for the Managed Identity.

Run the following T-SQL script in your Azure SQL Database:

CREATE USER jbdbreindex FROM EXTERNAL PROVIDER;
ALTER ROLE db_owner ADD MEMBER jbdbreindex;

This grants db_owner permissions to the Managed Identity, allowing it to execute maintenance tasks.

πŸ–₯️ Step 3: Create an Azure Automation Runbook

Next, let’s create a PowerShell Runbook that connects to Azure SQL Database using the Managed Identity and executes the IndexOptimize stored procedure.

  1. In Azure Portal, navigate to Automation Accounts β†’ Runbooks.
  2. Click Create a Runbook.
  3. Provide a name (e.g., IndexMaintenanceRunbook), select PowerShell as the Runbook type.
  4. Paste the following PowerShell script:
Write-Output "Index Maintenance started"

# Instantiate the connection to the SQL Database
$sqlConnection = new-object System.Data.SqlClient.SqlConnection

# Connect using Managed Identity
Connect-AzAccount -Identity

# Get a Token
$token = (Get-AzAccessToken -ResourceUrl https://database.windows.net ).Token

# Initialize Connection String
$sqlConnection.ConnectionString = "Data Source=jbsserver.database.windows.net;Initial Catalog=jbdb;Connect Timeout=60"

# Set the Token for authentication
$sqlConnection.AccessToken = $token

# Open the connection
$sqlConnection.Open()
Write-Output "Azure SQL database connection opened"

# Define the SQL Command
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.CommandTimeout = 0
$sqlCommand.Connection = $sqlConnection

Write-Output "Issuing command to run stored procedure"

# Execute IndexOptimize stored procedure
$sqlCommand.CommandText= "EXECUTE dbo.IndexOptimize
@Databases = 'jbdb',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 = 10,
@FragmentationLevel2 = 30,
@LogToTable='Y'"

$result = $sqlCommand.ExecuteNonQuery()
Write-Output "Stored procedure execution completed"

# Close connection
$sqlConnection.Close()
Write-Output "Run completed"
  1. Click Save and Publish the Runbook.

⏰ Step 4: Schedule the Runbook

Now, let’s schedule the Runbook to run automatically.

  1. Go to Automation Account β†’ Runbooks.
  2. Select your Runbook (IndexMaintenanceRunbook).
  3. Click Schedules β†’ Add a Schedule.
  4. Set the recurrence (e.g., Daily at Midnight).
  5. Link the schedule to the Runbook.

πŸ“Š Step 5: Monitor Runbook Execution

To verify successful execution:

  1. Go to Automation Account β†’ Runbooks β†’ Job History.
  2. Check if the Runbook ran successfully.
  3. Use SELECT * FROM dbo.CommandLog in SQL to view maintenance logs.

πŸŽ‰ Conclusion

Congratulations! 🎊 You have successfully scheduled Index Maintenance on Azure SQL Database securely using Azure Automation, PowerShell, and Managed Identity. This approach ensures:

  • πŸ”’ No explicit credentials are stored in scripts.
  • πŸ“ˆ Automated performance tuning for SQL Database.
  • πŸ› οΈ Seamless execution with minimal manual intervention.