nolock在SQL Server 2008中的临时表上

时间:2011-09-16 18:44:59

标签: sql-server sql-server-2008

添加with (Nolock)是否会在从临时表中进行选择时减少争用,或者SQL Server是否足够智能,以便不首先在临时表上创建争用?

PS:是的我知道READUNCOMMITTED的危险。

select * from #myTempTable

VS

select * from #myTempTable with (nolock) --is this faster?

3 个答案:

答案 0 :(得分:9)

您可以使用跟踪标志1200(在开发计算机上,因为我认为这是全局的)来查看为自己取出的锁

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

对于一个全球临时表,毫不奇怪,它会带来更大的不同。

虽然本地#temp表的锁类型仍然存在细微差别。我重现

下面输出的那部分
#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 

编辑:上述结果适用于堆。对于具有聚簇索引的临时表,结果如下。

#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

堆版本BULK_OPERATION锁定的原因是explained here。但可以看出,锁定开销几乎都是最小的。

答案 1 :(得分:5)

由于临时表的范围是相同的连接,因此不太可能有太大的区别。

你只是在同一个连接中与自己竞争锁,如果你正在阅读临时表,那么你可能是唯一一个这样做的人。

通常,最好不要过度优化和信任SQL Server查询引擎以完成其工作。等到你遇到问题之后再尝试解决问题。

编辑(稍微偏离主题):(更新后的链接)

但是,在创建临时表时,会围绕整个tempdb的影响进行一些讨论。有可能优化 - see options here(但这是一篇旧文章 - SQL Server 6.5 / 7.0),它可能会自动向SQL Server 2000向上处理该场景

但是,我建议您在解决问题之前等到问题为止。

答案 2 :(得分:0)

根据您的查询,它可以产生巨大的差异。 我只需在临时表上添加WITH(NO LOCK),就可以将查询执行时间从1295减少到590。结果可能会有所不同。