SQL Server - 临时表与物理表

Wil*_*l A 14 performance sql-server

我的工作场所正在进行一项运动,不再使用 #temp 表,而是使用带有 SPID 的永久物理表。每当人们以前将 INSERTed INTO #temp 表时,现在INSERT INTO dbo.MyPermanentTable (SPID, ...) VALUES (@@SPID, ...)都需要一个 - 以及DELETE FROM dbo.MyPermanentTable WHERE SPID = @@SPID在例如存储过程开头的一堆语句。此外,不用说,在使用这些“用于存储临时数据的永久表”的任何地方,都必须小心包含WHERE SPID = @@SPID.

转向这种做法背后的逻辑是,它将提高运行查询的服务器的整体性能(通过减少 tempdb 中的 I/O 和争用)。由于多种原因,我并不热衷于这种方法 - 它很丑陋,有潜在危险,并且似乎很可能会损害使用新方案的那些查询的性能。

有没有人有任何使用这种或类似方法来消除#temp 表的经验?

Rem*_*anu 18

可以很容易地证明,它不会减少 IO 或争用,而是增加两者。

  • IO:从#temp 表中插入、读取或删除的每一行现在都将从@@SPID 表中插入、读取或删除。但是每一行都会增加一个额外的@@SPID 列,因此需要的页面数会稍微增加,IO 会稍微大一点。但更重要的是,删除#temp 表和会话初始化新会话的#temp表现在必须用 模拟DELETE FROM @@spidTable WHERE spid = @@SPID,因此截断/创建操作(即页面范围管理操作)将被转换在行操作中,慢无比。
  • 争用:在#temp 表上使用页锁的每次扫描现在都有可能锁定具有不相关 spid 行的页,从而产生以前不存在的争用。每次执行更多达到锁升级阈值的更新都有机会将锁升级到表锁,从而阻止所有其他 spid。

因此,虽然您不会在 tempdb 中遇到神话般的 IAM/SGAM/GAM 争用,但发生这种情况的唯一原因是您的操作会因普通的额外 IO 和额外争用而变得慢得多。