添加with (Nolock)
是否会在从临时表中进行选择时减少争用,或者SQL Server是否足够智能,以便不首先在临时表上创建争用?
PS:是的我知道READUNCOMMITTED的危险。
select * from #myTempTable
VS
select * from #myTempTable with (nolock) --is this faster?
答案 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。结果可能会有所不同。