Problems with Local Variables

Q: Using local variables in statements and procedures can cause poor cardinality estimates. Alternative solutions can include rewriting the query to use literals instead of variables, using sp_executesql with a constructed statement that uses literals, or using a stored procedure with parameters (not local variables). Does using these options affect the use of statistics or change the way SQL Server behaves?

A: The problem with local variables is that they have unknown values at the time the query plan is compiled. As a result, SQL Server uses unknown statistics information (i.e., nonspecific value) during compilation.

Generating a specific statistic from a nonspecific value seems complicated, but it’s fairly easy to do in SQL Server. For every statistic, SQL Server keeps averages in addition to the histogram (which has specific values). According to the MSDN white paper “ Statistics Used by the Query Optimizer in Microsoft SQL Server 2008,” the histogram-based value (and the value obtained through parameter sniffing) is typically better. However, because a lot of commands and procedures (sp_executesql and stored procedures in general) save the plan based only on the first execution (when one isn’t already found in the plan cache), then subsequent executions can have performance problems if their most optimal plan isn’t the same as the one that the first execution created, compiled, or saved.

The end result is that you might need to force SQL Server to not save the compiled plan in the plan cache so that a plan is compiled on each execution. One clever way to accomplish this is through dynamic string execution, which is when you build a string to execute with the command EXECUTE('string').

Dynamic string execution follows essentially the same rules as an ad hoc statement (which can be parameterized, saved, and reused), but the rules are so strict that the compiled plan is unlikely to be saved. As a result, dynamic string execution statements are typically recompiled on each execution, with their literal values. This means that you pay the overhead of recompilation but get the (likely) benefit of a better plan. However, you have to be careful of SQL injection.

For information about how to eliminate SQL injection by protecting parameters and using EXECUTE AS (with a login-less database user), see my blog post “ Little Bobby Tables, SQL Injection and EXECUTE AS.” My blog also includes the general category Optimizing Procedural Code. But because there are a variety of parameter-related problems (each with different solutions, as well as different pros and cons for each solution), finding the best solution is a bit more confusing.

Please or Register to post comments.

What's SQL Server Questions Answered?

Practical tips and answers to many of your questions about SQL Server including database management and performance issues.


Paul S. Randal

Paul Randal worked on Microsoft's SQL Server team for nine years in development and management roles, writing many of the DBCC commands. Randal was ultimately responsible for SQL Server 2008'...

Kimberly L. Tripp

Kimberly L. Tripp has been working with SQL Server since 1990, and she’s worked as a consultant, trainer, speaker, and writer specializing in core SQL Server performance tuning and availability...
Blog Archive

Sponsored Introduction Continue on to (or wait seconds) ×