SQL SERVER 2025, Why Your SQL Query Is Burning CPU (And You Don’t See It)

Why Your SQL Query Is Burning CPU (And You Don’t See It) ๐Ÿ”ฅ

Hi SQL Server Guys,

๐Ÿ‘‰ If you missed my previous post, check it out here:
SQL Server: Stop Defragmenting! The Auto Index Compaction Feature That Changes Everything

Your query is slow.
You check IO.
Everything looks fine.

So… what’s killing performance?

๐Ÿ‘‰ CPU. 


๐Ÿง  CPU vs IO (Simple but Critical)

  • IO-bound → waiting on disk (reads, writes)
  • CPU-bound → heavy computations

Most people only look at IO. That’s a mistake.

❗ If IO is low and the query is still slow… CPU is your suspect.


๐Ÿ”ฅ Case #1 – Functions on Columns (The Silent Killer)


SELECT *
FROM Orders
WHERE YEAR(OrderDate) = 2025;

❌ Problem:

  • Function applied on column
  • Index NOT used
  • Full scan + CPU spike

✔️ Fix:


WHERE OrderDate >= '2025-01-01'
AND OrderDate < '2026-01-01'

๐Ÿ’ฃ Functions on columns don’t just break indexes… they burn CPU.


๐Ÿ”ฅ Case #2 – Scalar UDF (The Invisible Killer)


SELECT dbo.CalculateDiscount(Amount)
FROM Orders;

❌ Problem:

  • Executed once per row
  • Breaks parallelism (in many cases)
  • Row-by-row execution

๐Ÿ’ฃ Scalar functions turn set-based SQL into row-by-row execution.


๐Ÿ”ฅ Case #3 – Sorting & Hashing


SELECT *
FROM Orders
ORDER BY Amount;

๐Ÿ‘‰ Without an index:

  • SORT operator
  • High CPU usage

Same for:

  • HASH JOIN
  • HASH AGGREGATE

๐Ÿ‘‰ These operators are CPU hungry by design.


๐Ÿ”ฅ Case #4 – Bad Cardinality = CPU Waste

If SQL Server estimates wrong:

  • Chooses HASH instead of NESTED LOOP
  • Or the opposite

๐Ÿ‘‰ Result: unnecessary CPU consumption.


๐Ÿงช Benchmark Proof (This Is Gold)


SET STATISTICS TIME ON;
SET STATISTICS IO ON;
Query CPU Time Logical Reads
With function 1500 ms ๐Ÿ ‰ 5000 (=)
Optimized 200 ms   ๐Ÿ Ÿ 5000 (=)

๐Ÿ‘‰ Same IO.
๐Ÿ‘‰ CPU drops dramatically.


๐Ÿš€ How to Find CPU Killers ... Try ourself!


SELECT TOP 10
    qs.total_worker_time / qs.execution_count AS avg_cpu,
    qs.execution_count,
    st.text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY avg_cpu DESC;

๐Ÿ‘‰ This shows your worst CPU offenders.

๐Ÿ’ฃ High CPU queries are invisible if you only look at IO.


๐Ÿ’ฃ Final Thought

Your query is not slow… it’s expensive.

Disk can be cached, instead CPU cannot!

๐Ÿ‘‰ When CPU saturates… the entire server suffers.

๐Ÿ‘‰ If you want performance… start looking beyond IO.



Comments and suggestions are welcome!

Luca Biondi @2026! 




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!