Published on

April 26, 2020

Understanding Dynamic SQL in SQL Server

When working with databases, you may have come across the term “Dynamic SQL.” Dynamic SQL is a programming technique that allows you to build SQL statements dynamically at runtime. This flexibility enables you to create more general-purpose SQL statements, as the full text of the statements may not be known until compilation.

However, while Dynamic SQL offers benefits, it can also lead to problems and concerns. In this article, I would like to share a real-life scenario where Dynamic SQL caused a significant issue in my environment.

One day, a client’s stored procedure started running for an unusually long time and eventually failed with the error message: “SQLSTATE = 42000 [Microsoft][SQL Server Native Client 11.0][SQL Server]Could not allocate a new page for database ‘TEMPDB’ because of insufficient disk space in filegroup DEFAULT.”

Upon analysis, I discovered that an insert statement within the procedure, which used Dynamic SQL to populate a temporary table, was the root cause of the problem. The issue occurred when a large volume of data qualified for insertion into the temporary table. The optimizer generated a suboptimal execution plan due to differences in the data pattern, resulting in excessive spills into the tempdb database.

Spilling occurs when a query consumes more memory than allocated and starts writing data to disk in the tempdb database. Multiple spills can quickly consume a significant amount of space in tempdb, leading to disk space issues and performance degradation.

To recreate the issue, I isolated the insert statement and executed it both with and without Dynamic SQL. The results were striking:

With Dynamic SQL:
Exec ('
insert into #Temp 
select f.objid
from table1
where f.lastchngdtime >  ' + @lstChngDt + '))
UNION
select f.objid
 from table2 f
 join table3 d1  on
 f.objid= d1.objid
where f.lastchngdtime >  ' + @lstChngDt + '))
UNION
select f.objid
 from table3 f
 join table4 d1  on
 f.objid= d1.objid
where f.lastchngdtime >  ' + @lstChngDt + '))
UNION
select f.objid
 from table4 f
 join table5 d1  on
 f.objid = d1.objid
where f.lastchngdtime >  ' + @lstChngDt + '))
UNION
select f.objid
 from table5 f
 join table6 d1  on
 f.objid= d1.objid 
where f.lastchngdtime >  ' + @lstChngDt + '))'

Without Dynamic SQL:

insert into #Temp 
select f.objid
from table1
where f.lastchngdtime >  @lstChngDt
UNION
select f.objid
 from table2 f
 join table3 d1  on
 f.objid= d1.objid
where f.lastchngdtime >  @lstChngDt 
UNION
select f.objid
 from table3 f
 join table4 d1  on
 f.objid= d1.objid
where f.lastchngdtime >  @lstChngDt
UNION
select f.objid
 from table4 f
 join table5 d1  on
 f.objid= d1.objid
where f.lastchngdtime >   @lstChngDt 
UNION
select f.objid
 from table5 f
 join table6 d1  on
 f.objid= d1.objid
where f.lastchngdtime >   @lstChngDt

After executing the Dynamic SQL version, the free space in tempdb dropped from 62161MB to 160MB. In contrast, the non-dynamic version left the free space at 61251MB.

This experiment clearly demonstrates the impact of Dynamic SQL on tempdb space usage. By avoiding Dynamic SQL and using static SQL statements, we can significantly reduce the likelihood of encountering similar issues.

It’s important for developers to evaluate the necessity of using Dynamic SQL in their code. While it offers flexibility, it can also introduce performance problems and resource constraints. By carefully considering the code logic and alternatives, developers can minimize the risk of encountering situations like the one described in this article.

Remember, Dynamic SQL should be used judiciously and only when absolutely necessary. By doing so, you can ensure the stability and performance of your SQL Server environment.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.