Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nolock on a temp table in SQL Server 2008

Does adding with (Nolock) reduce contention when selecting from temp tables, or is SQL Server smart enough to not create contention on temp tables in the first place?

PS: Yes I am aware of the dangers of READUNCOMMITTED.

select * from #myTempTable

vs

select * from #myTempTable with (nolock) --is this faster?
like image 325
dan Avatar asked Sep 16 '11 18:09

dan


People also ask

Can we use Nolock in temp table?

While NOLOCK can "help" queries against *permanent* tables, it does not quite have the same effect against *temporary* tables - SQL Server knows that it doesn't have to worry about blocking other readers or writers, because #temp tables are scoped to a single, specific session.

How can use Nolock in stored procedure in SQL Server?

The WITH (NOLOCK) table hint is used to override the default transaction isolation level of the table or the tables within the view in a specific query, by allowing the user to retrieve the data without being affected by the locks, on the requested data, due to another process that is changing it.

What is difference between Nolock and with Nolock?

The NOLOCK and WITH(NOLOCK) table hints functionalities are the same. However, it is recommended to use WITH(NOLOCK) is required due to the following reasons. Omitting the WITH KEYWORD is a deprecated feature: You should not omit WITH Keyword, as per the Microsoft docs.


1 Answers

You can use trace flag 1200 (on a development machine as I think this is global) to see the locks taken out for yourself

SET NOCOUNT ON;

CREATE TABLE ##T
(
X INT
)

INSERT INTO ##T 
SELECT number
FROM master..spt_values

CREATE TABLE #T
(
X INT
)
INSERT INTO #T
SELECT *
FROM ##T

/*Run the commands first with the trace flag off so the locking
info is less full of irrelevant stuff about plan compilation 
*/
GO

PRINT '##T Read Committed'
SELECT COUNT(*) FROM ##T
PRINT '##T NOLOCK'
SELECT COUNT(*) FROM ##T WITH (NOLOCK)
PRINT '##T Finished'

GO

PRINT '#T Read Committed'
SELECT COUNT(*) FROM #T
PRINT '#T NOLOCK'
SELECT COUNT(*) FROM #T WITH (NOLOCK)
PRINT '#T Finished'

GO

DBCC TRACEON(-1,3604)
DBCC TRACEON(-1,1200)

GO

PRINT '##T Read Committed'
SELECT COUNT(*) FROM ##T
PRINT '##T NOLOCK'
SELECT COUNT(*) FROM ##T WITH (NOLOCK)
PRINT '##T Finished'

GO

PRINT '#T Read Committed'
SELECT COUNT(*) FROM #T
PRINT '#T NOLOCK'
SELECT COUNT(*) FROM #T WITH (NOLOCK)
PRINT '#T Finished'

GO

DBCC TRACEOFF(-1,3604)
DBCC TRACEOFF(-1,1200)

DROP TABLE ##T
DROP TABLE #T

For a global temp table it unsurprisingly makes more of a difference.

There is still a small difference in type of lock for local #temp tables though. I reproduce that part of the output below

#T Read Committed
Process 56 acquiring IS lock on OBJECT: 2:301244128:0  (class bit0 ref1) result: OK

Process 56 acquiring S lock on OBJECT: 2:301244128:0  (class bit0 ref1) result: OK

Process 56 releasing lock on OBJECT: 2:301244128:0 

#T NOLOCK
Process 56 acquiring Sch-S lock on OBJECT: 2:301244128:0  (class bit0 ref1) result: OK

Process 56 acquiring S lock on HOBT: 2:9079256880114171904 [BULK_OPERATION] (class bit0 ref1) result: OK

Process 56 releasing lock on OBJECT: 2:301244128:0 

Edit: The above results are for a heap. For temp tables with a clustered index the results are below.

#T Read Committed
Process 55 acquiring IS lock on OBJECT: 2:1790629422:0  (class bit0 ref1) result: OK

Process 55 acquiring S lock on OBJECT: 2:1790629422:0  (class bit0 ref1) result: OK

Process 55 releasing lock on OBJECT: 2:1790629422:0 

#T NOLOCK
Process 55 acquiring Sch-S lock on OBJECT: 2:1790629422:0  (class bit0 ref1) result: OK

Process 55 releasing lock on OBJECT: 2:1790629422:0 

#T Finished

The reason for the BULK_OPERATION lock on the heap version is explained here. But it can be seen that the locking overhead is pretty minimal whatever.

like image 128
Martin Smith Avatar answered Sep 27 '22 18:09

Martin Smith