SQL Server 2025 Series : ABORT_QUERY_EXECUTION Explained with Full Live Demo!

If you manage production workloads, you’ve probably seen situations where one problematic query keeps hurting performance for everyone else. In SQL Server 2025, Microsoft highlights ABORT_QUERY_EXECUTION as a Query Store hint that lets administrators block the future execution of a known problematic query without changing application code. That makes it a practical DBA-focused safeguard when you need control quickly.

In this blog, I’ll explain what ABORT_QUERY_EXECUTION is, why it matters, the prerequisites, and then walk through a full live demo using only the code shown below. I’ll also show how to verify whether the hint is configured and how to list blocked queries recorded in Query Store. Microsoft’s product and demo references position this feature as part of the broader query-processing and administrative control improvements in SQL Server 2025.


What is ABORT_QUERY_EXECUTION?

ABORT_QUERY_EXECUTION is a query hint showcased for SQL Server 2025 that can be applied through Query Store hints to block future executions of a specific query. The available Microsoft and demo references consistently describe it as an administrative control for stopping a known bad query from continuing to impact workload stability, while avoiding application code changes.

One important clarification: this feature is described as preventing future executions of the targeted query. The references do not describe it as a general-purpose replacement for terminating a query that is already running.


Why was this introduced?

The purpose is simple and practical. Sometimes a query is known to be expensive or disruptive, but the application team cannot change the code immediately. In that situation, Query Store hints already provide a way to influence query behavior without redeploying code, and ABORT_QUERY_EXECUTION extends that model by allowing the query to be blocked from future execution.

Available references describe this feature as a way to stop rogue or problematic queries from harming the rest of the workload and to improve reliability during incidents. That is what makes it a useful operational safety valve for DBAs.


Prerequisites

Before testing this feature, the main prerequisite is that Query Store must be enabled, because ABORT_QUERY_EXECUTION works through Query Store hints. This requirement is explicitly reflected in the demo references and supporting guidance.

For this walkthrough, you need:

  • SQL Server 2025
  • A database where your demo query can be captured in Query Store
  • Query Store enabled for that database

Full Demo Code

-- ABORT_QUERY_EXECUTION
CREATE OR ALTER procedure [dbo].[usp_procdisplaydata] @Col2 int
as
begin
SELECT top (150000)
[Col1],
[Col2],
[Col3],
[Col4],
[Col5]
FROM dbo.Table1
WHERE [Col2] = @Col2
ORDER BY [Col3];
END
EXEC [dbo].[usp_procdisplaydata] @Col2=2
SELECT TOP (20)
q.query_id,
qt.query_sql_text,
rs.count_executions,
rs.avg_duration,
rs.last_duration
FROM sys.query_store_query_text qt
JOIN sys.query_store_query q
ON qt.query_text_id = q.query_text_id
JOIN sys.query_store_plan p
ON q.query_id = p.query_id
JOIN sys.query_store_runtime_stats rs
ON p.plan_id = rs.plan_id
WHERE qt.query_sql_text LIKE N'%SELECT top (150000)%'
ORDER BY rs.last_execution_time DESC;
GO -- Query Id 38
EXEC sys.sp_query_store_set_hints
@query_id = 38,
@query_hints = N'OPTION (USE HINT (''ABORT_QUERY_EXECUTION''))';
GO
SELECT *
FROM sys.query_store_query_hints
WHERE query_id = 38;
GO
EXEC [dbo].[usp_procdisplaydata] @Col2=2
EXEC sys.sp_query_store_clear_hints
@query_id = 38;
GO
-- Blocked queries in Query Store
SELECT qsh.query_id,
q.query_hash,
qt.query_sql_text
FROM sys.query_store_query_hints AS qsh
INNER JOIN sys.query_store_query AS q
ON qsh.query_id = q.query_id
INNER JOIN sys.query_store_query_text AS qt
ON q.query_text_id = qt.query_text_id
WHERE UPPER(qsh.query_hint_text) LIKE '%ABORT[_]QUERY[_]EXECUTION%'

Step-by-Step Demo Explanation

1) Create the procedure and execute it once

The first part of the demo creates a stored procedure and executes it so the query text is captured in Query Store. That step is important because the feature is implemented through Query Store hints, and you need the corresponding query_id before you can apply the hint.

2) Find the query in Query Store

The next query searches the Query Store catalog views using the text pattern SELECT top (150000) to identify the relevant query and retrieve its query_id. In this demo script, the query id used is 38. The overall approach aligns with the feature’s dependency on Query Store metadata.

3) Apply ABORT_QUERY_EXECUTION

The core configuration step is:

EXEC sys.sp_query_store_set_hints
@query_id = 38,
@query_hints = N'OPTION (USE HINT (''ABORT_QUERY_EXECUTION''))';

This applies the ABORT_QUERY_EXECUTION query hint through Query Store for the specific query. The available demo and product materials explicitly show this feature being implemented through sp_query_store_set_hints.

4) Verify that the hint is configured

The following verification query checks the Query Store catalog view for the configured hint:

SELECT *
FROM sys.query_store_query_hints
WHERE query_id = 38;

This is a practical way to verify whether ABORT_QUERY_EXECUTION has been configured for that query in your database.

5) Execute the procedure again

After the hint is applied, the procedure is executed again so you can validate the configured behavior. Based on the available references, ABORT_QUERY_EXECUTION is designed to block future executions of the targeted query once the hint is in place.

6) Clear the hint

Once testing is complete, the hint is removed using:

EXEC sys.sp_query_store_clear_hints
@query_id = 38;

This completes the full end-to-end lifecycle: identify the query, apply the hint, verify it, test it, and clear it when it is no longer needed.

7) List blocked queries in Query Store

The final query in the script looks for entries in sys.query_store_query_hints where the configured hint text contains ABORT_QUERY_EXECUTION. This is useful when you want to audit or review queries that have been configured with this hint

SELECT qsh.query_id,
q.query_hash,
qt.query_sql_text
FROM sys.query_store_query_hints AS qsh
INNER JOIN sys.query_store_query AS q
ON qsh.query_id = q.query_id
INNER JOIN sys.query_store_query_text AS qt
ON q.query_text_id = qt.query_text_id
WHERE UPPER(qsh.query_hint_text) LIKE '%ABORT[_]QUERY[_]EXECUTION%'

ABORT_QUERY_EXECUTION is one of the more practical DBA-oriented capabilities highlighted in SQL Server 2025. It gives administrators a way to block the future execution of a known problematic query using Query Store hints, without changing application code. That makes it especially valuable when immediate workload protection is needed.


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=SjjC18u-jjM


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 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.

Unleashing SQL Server 2022: Enhancements to sys.dm_exec_query_statistics_xml

In the world of data management and analysis, SQL Server 2022 has brought numerous improvements and enhancements, one of the most notable being the advancements to the dynamic management view (DMV) sys.dm_exec_query_statistics_xml. This DMV provides detailed runtime statistics about query execution, which is invaluable for performance tuning and query optimization.

In this blog, we will explore the enhancements to sys.dm_exec_query_statistics_xml in SQL Server 2022 using the JBDB database. We’ll walk through a comprehensive business use case, demonstrate these enhancements with T-SQL queries, and show how these can be leveraged for better performance insights.

Business Use Case: Optimizing an E-commerce Database πŸ›’

Imagine you are a database administrator for JBDB, an e-commerce platform with millions of users and transactions. Ensuring optimal query performance is crucial for providing a seamless user experience. You need to monitor query performance, identify slow-running queries, and understand execution patterns to make informed optimization decisions.

The JBDB Database Schema

For this demo, we’ll use a simplified version of the JBDB database with the following schema:

  • Customers: Stores customer information.
  • Orders: Stores order details.
  • OrderItems: Stores items within an order.
  • Products: Stores product details.

CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    Name NVARCHAR(100),
    Email NVARCHAR(100),
    CreatedAt DATETIME
);

CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(100),
    Price DECIMAL(10, 2),
    Stock INT
);

CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT FOREIGN KEY REFERENCES Customers(CustomerID),
    OrderDate DATETIME
);

CREATE TABLE OrderItems (
    OrderItemID INT PRIMARY KEY,
    OrderID INT FOREIGN KEY REFERENCES Orders(OrderID),
    ProductID INT FOREIGN KEY REFERENCES Products(ProductID),
    Quantity INT,
    Price DECIMAL(10, 2)
);
INSERT INTO Customers (CustomerID, Name, Email, CreatedAt)
VALUES 
(1, 'John Doe', 'john.doe@example.com', '2023-01-10'),
(2, 'Jane Smith', 'jane.smith@example.com', '2023-02-15'),
(3, 'Emily Johnson', 'emily.johnson@example.com', '2023-03-22'),
(4, 'Michael Brown', 'michael.brown@example.com', '2023-04-05'),
(5, 'Sarah Davis', 'sarah.davis@example.com', '2023-05-30');


INSERT INTO Products (ProductID, ProductName, Price, Stock)
VALUES 
(1, 'Laptop', 999.99, 50),
(2, 'Smartphone', 499.99, 150),
(3, 'Tablet', 299.99, 75),
(4, 'Headphones', 149.99, 200),
(5, 'Smartwatch', 199.99, 100);

INSERT INTO Orders (OrderID, CustomerID, OrderDate)
VALUES 
(1, 1, '2023-06-15'),
(2, 2, '2023-07-20'),
(3, 3, '2023-08-25'),
(4, 4, '2023-09-10'),
(5, 5, '2023-10-05');

INSERT INTO OrderItems (OrderItemID, OrderID, ProductID, Quantity, Price)
VALUES 
(1, 1, 1, 1, 999.99),
(2, 1, 4, 2, 149.99),
(3, 2, 2, 1, 499.99),
(4, 2, 5, 1, 199.99),
(5, 3, 3, 2, 299.99),
(6, 4, 1, 1, 999.99),
(7, 4, 2, 1, 499.99),
(8, 5, 5, 2, 199.99),
(9, 5, 3, 1, 299.99);

Enhancements to sys.dm_exec_query_statistics_xml πŸ†•

SQL Server 2022 introduces several key enhancements to sys.dm_exec_query_statistics_xml, including:

  1. Enhanced Plan Information: More detailed execution plan information is now available.
  2. Wait Statistics: Comprehensive wait statistics are included to identify bottlenecks.
  3. Query Store Integration: Better integration with the Query Store for historical analysis.

Demonstrating Enhancements with T-SQL Queries πŸ“Š

Let’s dive into some T-SQL queries to see these enhancements in action.

Step 1: Capture a Sample Query Execution

First, we’ll execute a sample query to fetch order details along with customer and product information.

SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price
FROM
Orders o
JOIN
Customers c ON o.CustomerID = c.CustomerID
JOIN
OrderItems oi ON o.OrderID = oi.OrderID
JOIN
Products p ON oi.ProductID = p.ProductID
WHERE
o.OrderDate BETWEEN '2023-01-01' AND '2023-12-31';

Step 2: Retrieve Query Statistics XML

Next, we’ll use sys.dm_exec_query_statistics_xml to retrieve detailed execution statistics for the above query.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
qst.sql_handle,
qst.plan_handle,
qst.execution_count,
qst.total_worker_time,
qst.total_elapsed_time,
qst.total_logical_reads,
qst.total_physical_reads,
qst.creation_time,
qst.last_execution_time,
q.text AS query_text,
qpx.query_plan
FROM
sys.dm_exec_query_stats AS qst
CROSS APPLY
sys.dm_exec_sql_text(qst.sql_handle) AS q
CROSS APPLY
sys.dm_exec_query_plan(qst.plan_handle) AS qpx
WHERE
q.text LIKE '%SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price%';

Step 3: Analyzing Enhanced Plan Information πŸ”

With SQL Server 2022, the execution plan XML now includes more detailed information about the query execution. You can parse the XML to extract specific details.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT 
    query_plan.value('(//RelOp/LogicalOp)[1]', 'NVARCHAR(100)') AS LogicalOperation,
    query_plan.value('(//RelOp/PhysicalOp)[1]', 'NVARCHAR(100)') AS PhysicalOperation,
    query_plan.value('(//RelOp/RunTimeInformation/RunTimeCountersPerThread/ActualRows)[1]', 'INT') AS ActualRows,
    query_plan.value('(//RelOp/RunTimeInformation/RunTimeCountersPerThread/ActualEndOfScans)[1]', 'INT') AS ActualEndOfScans
FROM 
    (SELECT CAST(qpx.query_plan AS XML) AS query_plan
     FROM sys.dm_exec_query_stats qs
     CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qpx
     WHERE qs.sql_handle = (SELECT sql_handle FROM sys.dm_exec_requests WHERE session_id = @@SPID)) AS x;

Step 4: Monitoring Wait Statistics ⏱️

Wait statistics help identify performance bottlenecks such as CPU, IO, or memory waits. SQL Server 2022 provides enhanced wait statistics in the query execution plans.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT 
    wait_type,
    wait_time_ms AS total_wait_time_ms,
    wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms,
    signal_wait_time_ms
FROM 
    sys.dm_exec_session_wait_stats
WHERE 
    session_id = @@SPID;

Leveraging Query Store Integration πŸ“ˆ

SQL Server 2022’s improved integration with the Query Store allows for historical query performance analysis, helping you understand performance trends and regressions.

SELECT 
    qsp.plan_id,
    qsp.query_id,
    qsqt.query_sql_text AS query_text,
    qsrs.count_executions AS execution_count,
    qsrs.avg_duration,
    qsrs.avg_cpu_time,
    qsrs.avg_logical_io_reads
FROM 
    sys.query_store_runtime_stats qsrs
JOIN 
    sys.query_store_plan qsp ON qsrs.plan_id = qsp.plan_id
JOIN 
    sys.query_store_query qsq ON qsp.query_id = qsq.query_id
JOIN 
    sys.query_store_query_text qsqt ON qsq.query_text_id = qsqt.query_text_id
WHERE 
    qsqt.query_sql_text LIKE '%SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price%';

Conclusion πŸŽ‰

The enhancements to sys.dm_exec_query_statistics_xml in SQL Server 2022 provide deeper insights into query performance, making it easier to identify and resolve performance issues. By leveraging these new capabilities, database administrators can ensure their SQL Server instances run more efficiently and effectively.

Feel free to experiment with the queries provided and explore the powerful new features SQL Server 2022 has to offer. Happy querying! πŸ§‘β€πŸ’»