SQL Server SELECT INTO and Blocking With Temp Tables
Asked Answered
P

8

28

So, recently a DBA is trying to tell us that we cannot use the syntax of

SELECT X, Y, Z
INTO #MyTable
FROM YourTable

To create temporary tables in our environment, because that syntax causes a lock on TempDB for the duration of the stored procedure executing. Now, I've found a number of things that detail how temporary tables work, scope of execution, cleanup and the like. But for the life of me, I don't see anything about blocking because of their use.

We are trying to find proof that we shouldn't have to go through and do CREATE TABLE #MyTable... for all of our temporary tables, but neither side can find proof. I'm looking for any insight SO people have.

Additional Information

Currently working with SQL Server 2005, and soon to be SQL Server 2008 (Enterprise editions)

Parting answered 19/8, 2009 at 21:18 Comment(0)
L
34

That advice has been floating around for a long time:

Bottlenecks in SQL Server 6.5

Many people use a SELECT...INTO query to create a temporary table, something like this:

SELECT * INTO #TempTable FROM SourceTable

While this works, it creates locks against the tempdb database for the duration of the SELECT statement (quite a while if you are trawling through a lot of data in the source table, and longer still if the SELECT...INTO is at the start of a longer-running explicit transaction) While the lock is in place, no other user can create temporary tables. The actual location of the bottleneck is a lock on tempdb system tables. In later versions of SQL Server, the locking model has changed and the problem is avoided.

Fortunately, it was only a problem for SQL 6.5. It was fixed in 7.0 and later.

Lithic answered 19/8, 2009 at 21:43 Comment(2)
Can you please update your answer with new functionality of SQL as your answer turn up first in Google search and it should be valid for latest version. TIA :)Roentgenotherapy
@RajShah What's out of date? Unless a later version broke it again, I can't imagine "It was fixed in 7.0 and later." is a statement that will go out of date. (And "was a problem for 6.5" certainly can't).Sorption
P
17

This will probably float around for a long time, feeding the pockets of various 'consultants'. Like all myths, it has a kernel of truth and a lot of BS.

The truth: SQL 2000 and previous versions had known contention issues around the allocation of extents in tempdb. The contention was true in fact in all databases, but more visible in tempdb due to some heavy tempdb usage. It is documented in KB328551:

When the tempdb database is heavily used, SQL Server may experience contention when it tries to allocate pages.

From the sysprocesses system table output, the waitresource may show up as "2:1:1" (PFS Page) or "2:1:3" (SGAM Page). Depending on the degree of contention, this may also lead to SQL Server appearing unresponsive for short periods.

These operations heavily use tempdb:
Repeated create and drop of temporary tables (local or global).
Table variables that use tempdb for storage purposes.
Work tables associated with CURSORS.
Work tables associated with an ORDER BY clause.
Work tables associated with an GROUP BY clause.
Work files associated with HASH PLANS.

Heavy and significant use of these activities may lead to the contention problems.

A trace flag -T1118 was added in SQL Server 2000 SP3 that was forcing SQL to use a round-robin algorithm for mixed pages allocations. This new algorithm, when correlated with the practice of deploying tempdb on top of a set of equal size files, one for each CPU, would alleviate the contention. The trace flag is still present in SQL 2005/2008, although its far less likely to be needed.

Everything else about this myth is pretty much BS.

  • does use of #temp tables cause blocking? No. At worst it increases contention under load in SQL 2000 and earlier, but that is a far cry from saying that it blocks anything. You would have to measure first and see that this is the case, and if so deploy the remediation measures (allocate one tempdb file per CPU, make them equal size, turn on -T1118)..
  • Does select ... into #temp block something for the duration of the select? Not really.
  • Does select ... into #temp block something for the duration of the stored procedure containing the select? Hell no. Just reading that claim and I burst into laugh.

For more details, there is this article: Misconceptions around TF1118.

Patrilineage answered 20/8, 2009 at 0:30 Comment(1)
if [select ... into #temp] is in transaction , before the transaction commit , [select * from sysobjects] will be blocked in any other session .Dacoity
O
11

Why not do the following?

SELECT X, Y, Z
INTO #MyTable
FROM YourTable
WHERE 1 = 2

The statement would run instantly - creating your temp table and avoiding any possible locking. Then you could insert into it as usual:

INSERT #MyTable
SELECT X, Y, Z
FROM YourTable
Ostmark answered 15/6, 2010 at 21:52 Comment(0)
S
1

You can get blocking if you create #temp tables inside a transaction. While this is generally not recommended I have seen this done a lot.

However the blocking this causes is on some system tables in tempdb that do not affect other connections from creating temp tables (except perhaps for SQL versions prior to 2000?). It does mean that running sp_spacesused on tempdb will block unless you set transaction isolation level to read uncommitted. Also viewing properties on tempdb from SSMS will fail and timeout no doubt because it is using read committed transaction isolation level.

Sunfish answered 2/11, 2010 at 0:3 Comment(0)
F
1

While SELECT INTO has been fixed from blocking the tempdb i would use caution when writing such code as under testing some system tables do get blocked.

Reference: http://www.sqlservercentral.com/Forums/Topic1642797-2799-1.aspx

Frisbee answered 10/3, 2016 at 13:6 Comment(0)
S
0

I would say lack of locking proof means no locking, which is your proof. Why would the method that the temp table is created in (CREATE or SELECT ... INTO) make a difference in locking TempDB?

Suspensory answered 19/8, 2009 at 21:24 Comment(3)
That is our thoughts and argument as well....but they are insisting that using SELECT INTO causes blocking for the duration of the stored procedure.Parting
I wonder why the temp table being locked is a concern as well. If it were a global temp table, that's a different story.Concupiscent
@rexem: The OP's DBA isn't saying that the temp table is locked, but that TempDB, the location of all temp tables, and other temp storage is locked. No idea on whether the DBA is right, I'll defer to wiser folks.Indemonstrable
G
0

Well if that were true then mssql would have problems, since any large query can make use of tempdb to hold a copy of the rows. This can often be seen in the query plans as a table spool or can be used by the HASH JOIN operator if it runs out of memory for its buckets.

You can look at using table variables, which mssql will try to store in memory and move to tempdb if they grow to large.

DECLARE @foo TABLE (x int, y int, z int)
INSERT INTO @foo(x, y, z) SELECT x, y, z FROM YourTable

Of course, you should evaluate if the temporary table and copy is required first. Though if the query is complex enough that using a temp table is far more readable it might also be complex enough for a temp table to be worthwhile.

Gaddis answered 19/8, 2009 at 21:42 Comment(0)
V
0

SELECT INTO #temp_table holds a shema lock in tempdb for the duration of the statement because part of the work it's accomplishing is creating the table. This is fundamentally different than first creating the table using CREATE TABLE #.... and then running a set based INSERT. SELECT INTO does have advantages over INSERT, in particular the operation is minimally logged if the recovery model of the database is simple or bulked log.

Vigorous answered 22/1, 2010 at 20:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.