I recently saw a server with trace flag 2453 configured. I hadn’t come across this trace flag before, so I did a little research. Microsoft says it allows “a table variable to trigger recompile when enough number of rows are changed”. This can lead to a more efficient execution plan. Trace flag 2453 is available in SP2 or greater for SQL Server 2012, CU3 or greater for SQL Server 2014 and RTM or greater for SQL Server 2016.
I was curious how a query using a table variable performed as compared to the “same” query using:
- trace flag 2453
- OPTION (RECOMPILE)
- a temporary table
DEMO SETUP
DECLARE @t1 TABLE (Id INT PRIMARY KEY CLUSTERED, DisplayName NVARCHAR(40)); INSERT INTO @t1 (Id, DisplayName) SELECT Id, DisplayName FROM Users; CREATE TABLE #t1 (Id INT PRIMARY KEY CLUSTERED, DisplayName NVARCHAR(40)); INSERT INTO #t1 (Id, DisplayName) SELECT Id, DisplayName FROM Users;
BASELINE
SELECT t1.Id, t1.DisplayName, Users.CreationDate FROM @t1 t1 JOIN Users ON t1.Id = Users.Id WHERE Users.CreationDate < '08/14/2008';
Table variable details:
TRACE FLAG 2453
DBCC TRACEON(2453); SELECT t1.Id, t1.DisplayName, Users.CreationDate FROM @t1 t1 JOIN Users ON t1.Id = Users.Id WHERE Users.CreationDate < '08/14/2008'; DBCC TRACEOFF(2453);
Table variable details:
OPTION(RECOMPILE)
SELECT t1.Id, t1.DisplayName, Users.CreationDate FROM @t1 t1 JOIN Users ON t1.Id = Users.Id WHERE Users.CreationDate < '08/14/2008' OPTION (RECOMPILE);
Table variable details:
TEMPORARY TABLE
SELECT #t1.Id, #t1.DisplayName, Users.CreationDate FROM #t1 JOIN Users ON #t1.Id = Users.Id WHERE Users.CreationDate < '08/14/2008';
Temporary table details:
THE RESULTS
The baseline query has a clustered index scan for the table variable since almost 3.5 million rows are returned from it. The other 3 queries have the same execution plan and stats IO output, with a clustered index seek on the table variable or temporary table since 963 rows are returned from it.
WHAT WOULD TARA DO?
Should you always use trace flag 2453 or OPTION (RECOMPILE) if you are using table variables? Maybe. But I’m leaning towards “it depends”. Microsoft says the “trace flag must be used with caution because it can increase number of query recompiles which could cost more than savings from better query optimization”.
Some people say to use table variables if the table will contain a small data set. I’ve been burned by that before. I’ve experienced poor performance when the table variable always only had one row in it. Switching it to a temporary table improved the performance dramatically. Your mileage may vary.
I’ll just stick with temporary tables.
Psst - use coupon code BeMyValentine for 50% off our online classes this week.