SQL Server SELECT INTO和使用临时表阻止

时间:2009-08-19 21:18:53

标签: sql-server stored-procedures temp-tables sqlperformance

所以,最近DBA试图告诉我们我们不能使用

的语法
SELECT X, Y, Z
INTO #MyTable
FROM YourTable

在我们的环境中创建临时表,因为该语法会在执行存储过程的持续时间内导致TempDB锁定。现在,我发现了一些详细说明临时表如何工作,执行范围,清理等的东西。但是对于我的生活,由于它们的使用,我没有看到任何关于阻挡的事情。

我们正试图找到我们不应该经历的证据,并为所有临时表执行CREATE TABLE #MyTable ...但是双方都无法找到证据。我正在寻找人们所拥有的任何见解。

其他信息

目前正在使用SQL Server 2005,很快将成为SQL Server 2008(企业版)

8 个答案:

答案 0 :(得分:34)

这个建议一直在for a long time

  

SQL Server 6.5中的瓶颈

     

许多人使用SELECT ... INTO查询   创建一个临时表,一些东西   像这样:

     

SELECT * INTO #TempTable FROM   sourceTable会

     

虽然这有效,但它会产生锁定   针对tempdb数据库的   SELECT语句的持续时间   (如果你正在拖网,很长一段时间   通过源中的大量数据   表,如果更长的话   SELECT ... INTO是一个开头的   长时间运行的显性事务)   虽然锁定到位,但没有其他   用户可以创建临时表。该   瓶颈的实际位置是   锁定tempdb系统表。在以后   SQL Server的版本,锁定   模型已经改变,问题是   避免。

幸运的是,这只是SQL 6.5的一个问题。它在7.0及更高版本中得到修复。

答案 1 :(得分:17)

这可能会浮动很长一段时间,为各种“顾问”的口袋提供食物。像所有神话一样,它有一个真实的内核和很多BS。

事实:SQL 2000和以前的版本已知存在tempdb中分配范围的争用问题。实际上,争用在所有数据库中都是正确的,但由于一些繁重的tempdb使用,在tempdb中更明显。它记录在KB328551

  

当tempdb数据库很重时   使用过,SQL Server可能会遇到   尝试分配时的争用   页面。

     

来自sysprocesses系统表   输出,waitresource可能会出现   为“2:1:1”(PFS页面)或“2:1:3”(SGAM   页)。取决于程度   争用,这也可能导致SQL   服务器似乎没有响应   短期。

     

这些操作大量使用tempdb:
  重复创建和删除临时   桌子(本地或全球)。
  使用tempdb进行存储的表变量   目的。
  与之关联的工作表   游标。
  与之关联的工作表   ORDER BY条款。
  与GROUP BY子句关联的工作表   与HASH PLANS相关的工作文件。

     

重要且重要的使用这些   活动可能会导致争用   问题。

在SQL Server 2000 SP3中添加了跟踪标志-T1118,该标志强制SQL使用循环算法进行混合页面分配。当与在一组相同大小的文件(每个CPU一个)上部署tempdb的实践相关联时,这种新算法将减轻争用。 SQL 2005/2008中仍然存在跟踪标志,尽管它不太可能需要。

关于这个神话的其他所有内容都是BS。

  • 使用#temp表导致阻塞?在最坏的情况下,在SQL 2000及更早版本中增加在负载下的争用,但这与说它阻止任何事情相去甚远。你必须先测量并看到这种情况,如果是这样的话,部署补救措施(为每个CPU分配一个tempdb文件,使它们大小相同,打开-T1118)..
  • 在选择的持续时间内选择...到#temp阻止某事吗?不是真的。
  • 在包含select的存储过程的持续时间内,选择...到#temp块中吗?一定不行。只是阅读那个说法,我就笑了。

有关详细信息,请参阅此文章:Misconceptions around TF1118

答案 2 :(得分:10)

为什么不这样做?

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

该语句将立即运行 - 创建临时表并避免任何可能的锁定。然后你可以像往常一样插入它:

INSERT #MyTable
SELECT X, Y, Z
FROM YourTable

答案 3 :(得分:1)

如果在事务中创建#temp表,则可能会阻塞。虽然这通常不推荐,但我已经看到了很多。

然而,导致阻塞的原因是tempdb中的某些系统表不会影响其他连接创建临时表(可能除了2000之前的SQL版本?)。它确实意味着在tempdb上运行sp_spaces将阻止,除非您将事务隔离级别设置为read uncommitted。另外,从SSMS查看tempdb上的属性将失败并且超时无疑是因为它使用了读提交的事务隔离级别。

答案 4 :(得分:0)

我会说没有锁定证明意味着没有锁定,这是你的证明。为什么创建临时表的方法(CREATE或SELECT ... INTO)会对锁定TempDB产生影响?

答案 5 :(得分:0)

如果这是真的那么mssql会有问题,因为任何大型查询都可以利用tempdb来保存行的副本。这通常可以在查询计划中看作表格假脱机,或者如果HASH JOIN运算符的内存耗尽,则可以由HASH JOIN运算符使用。

您可以查看使用表变量,mssql将尝试存储在内存中,如果它们变大,则移动到tempdb。

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

当然,您应该首先评估是否需要临时表和副本。虽然如果查询足够复杂,使用临时表的可读性要高得多,那么临时表也可能是值得的。

答案 6 :(得分:0)

SELECT INTO #temp_table在语句的持续时间内持有tempdb的shema锁,因为它正在完成的部分工作是创建表。这与使用CREATE TABLE #....首先创建表然后运行基于集合的INSERT的根本不同。 SELECT INTO确实优于INSERT,特别是如果数据库的恢复模型是简单或批量日志,则操作最少记录。

答案 7 :(得分:0)

虽然已修复SELECT INTO以阻止tempdb,但在编写此类代码时会谨慎,因为在测试中某些系统表会被阻止。

参考: blog post