August 28, 2026DBA

Temp Tables vs. Table Variables: Cutting Through the Myths

Stop relying on outdated myths about memory versus disk. This guide provides a definitive decision matrix and technical breakdown for choosing between #temp tables and @table variables in production environments.

The Quick Decision Matrix

If you are in a hurry, use this logic. I have spent years cleaning up production outages caused by the wrong choice here.

Use a Temp Table (#Table) if:

  • You are dealing with more than 10,000 rows.
  • You need to create indexes after the table is populated.
  • You need to perform complex joins or multiple passes over the data.
  • You need the table to be visible to child stored procedures.

Use a Table Variable (@Table) if:

  • You have a very small dataset (less than 1,000 rows).
  • You need to ensure the data persists even if a transaction rolls back.
  • You want to minimize recompiles in a high-concurrency environment.
  • The logic is a simple 'scratchpad' for a single scope.

The Memory Myth

Let’s kill the most common misconception first: "Table variables live in memory and temp tables live on disk." This is false. Both reside in tempdb. If your table variable grows large enough, it will spill to disk just like a temp table. The difference isn't where they live; it's how the SQL Server Optimizer treats them.

Historically, table variables did not have statistics. The optimizer would assume a cardinality of 1 row, regardless of whether you had ten rows or ten million. While newer versions of SQL Server (2017+) have introduced deferred compilation to help mitigate this, relying on it is risky. Temp tables, conversely, support full distribution statistics, meaning the optimizer knows exactly what it's dealing with before it generates an execution plan.

Scope and Transactional Integrity

Temp tables are session-scoped. If you create a #temp table in a parent procedure, the child procedure can see it. This is powerful but can lead to 'spaghetti code' if abused. Table variables are strictly local to the batch or function where they are declared.

More importantly, table variables do not participate in transactions. If you insert five rows into a @table variable, start a transaction, insert five more, and then issue a ROLLBACK, the @table variable will still contain all ten rows. The #temp table, however, will respect the rollback and revert to five rows. In complex financial logic, choosing the wrong one can lead to silent data corruption in your application logic.

Performance and Recompilation

One area where table variables shine is the reduction of stored procedure recompilations. A temp table is considered a DDL change in many contexts. If you are running a high-throughput procedure thousands of times per minute, the overhead of creating and dropping temp tables can cause metadata contention in tempdb and trigger frequent recompiles.

Table variables are treated more like variables. They generally result in fewer recompilations, which is why they are the preferred choice for small, high-speed lookups. However, as soon as that 'small' lookup grows to a few thousand rows, the lack of an index or poor cardinality estimation will cost you far more in execution time than you saved in compilation time.

Parallelism and Indexing

Until recently, SQL Server would not generate parallel execution plans for queries that modified table variables. While this has improved, temp tables remain the king of performance for large-scale data processing because they fully support parallel operations and sophisticated indexing.

You can create indexes on a temp table after it has been populated. With a table variable, you are limited to defining indexes at the time of declaration (via primary keys or unique constraints). In a production tuning scenario, being able to add a non-clustered index to a #temp table mid-stream is a lifesaver.

Final Verdict

Stop overthinking the 'memory' aspect and start thinking about the 'optimizer' aspect. If your data is large enough that the execution plan matters, use a temp table. If your data is tiny and you need to avoid the overhead of DDL, use a table variable. When in doubt, default to a #temp table; it is the safer, more scalable choice for 90% of DBA tasks.

Related services

Dealing with this in production? Here's how we help.

Book a free 30-min consult

← All posts

Keep reading