2009-08-19 87 views
24

所以,最近一个DBA是想告诉我们,我们不能使用的SQL Server的SELECT INTO和阻止随着临时表

SELECT X, Y, Z 
INTO #MyTable 
FROM YourTable 

的语法来创建我们的环境中临时表,因为这句法会导致锁定在存储过程执行期间在TempDB上执行。现在,我已经发现了许多详细说明临时表的工作方式,执行范围,清理等等的内容。但是对于我的生活,我没有看到任何关于阻塞因为它们的使用。

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

其他信息

目前与SQL Server 2005的工作,并很快被SQL Server 2008的(企业版)

+0

你为什么不考呢? – automatic 2009-08-19 21:24:26

+0

我们一直没有看到任何屏蔽..... 我们正试图找到某种形式的证据,或更好的文档 – 2009-08-19 21:41:15

回答

34

该建议已被左右浮动for a long time

瓶颈在SQL Server 6.5

很多人使用SELECT ... INTO查询 创建一个临时表,一些 这样的:

SELECT * INTO #TempTable FROM sourceTable会

虽然该W兽人,它创建锁 对SELECT语句 的 期间tempdb数据库(相当长一段时间,如果你有拖网 通过源 表中的大量数据,以及更长的犹若 SELECT ... INTO位于 长时间运行的显式事务处理的开始处) 锁定就位时,没有其他 用户可以创建临时表。 瓶颈的实际位置是对tempdb系统表的一个 锁定。在稍后的 版本的SQL Server中,锁定 模型已更改,并且问题是 可以避免。

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

+3

+1我认为dba的建议然后属于神话的范畴 – 2009-08-19 21:49:13

+0

+1链接到一个恒星的解决方法 - WHERE 1 = 0 – SqlRyan 2009-08-23 15:27:52

+0

您可以请更新您的答案与SQL的新功能,因为您的答案首先在谷歌搜索,它应该是有效的最新版本。 TIA :) – 2014-08-26 14:29:32

0

我会说缺乏锁定证据意味着没有锁定,这是你的证明。为什么在临时表中创建的方法(CREATE或SELECT ... INTO)在锁定TempDB方面有所作为?

+0

这就是我们的想法和论点......但他们是坚持使用SELECT INTO会在存储过程期间导致阻塞。 – 2009-08-19 21:41:57

+0

我想知道为什么临时表被锁定也是一个问题。如果它是一个全球临时表,那是一个不同的故事。 – 2009-08-19 21:42:53

+0

@rexem:OP的DBA并不是说临时表已被锁定,但TempDB,所有临时表的位置以及其他临时存储都被锁定。不知道DBA是否正确,我会推迟到聪明的人。 – 2009-08-20 03:51:13

0

那么如果这是真的,那么mssql会有问题,因为任何大型查询都可以使用tempdb来保存行的副本。这通常可以在查询计划中作为表假脱机工具看到,或者如果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 

当然,你应该评估是否需要首先临时表和副本。尽管如果查询足够复杂以至于使用临时表的可读性要高得多,那么对于临时表而言,值也可能足够复杂。

16

这可能会浮现很长一段时间,喂养各种'顾问'的口袋。像所有的神话一样,它具有真理和许多BS的核心。

事实:SQL 2000和以前的版本已经知道有关tempdb中扩展区分配的争用问题。实际上,所有数据库中的争用都是真实的,但由于tempdb使用量过大,在tempdb中更加明显。据记载在KB328551

当tempdb数据库是大量使用时,SQL Server可能会遇到 竞争,当它试图分配 页 。

从sysprocesses系统表 输出,waitresource该可能显示 为 “2:1:1”(PFS页)或 “2:1:3”(SGAM 页)。根据 争用的程度,这也可能导致SQL 服务器短时间内显示为无响应的 。

这些操作大量使用tempdb:
重复创建和临时 表降(本地或全局)。
使用tempdb存储 目的的表变量。
与 CURSORS相关的工作表。
与 关联的工作表是一个ORDER BY子句。
与GROUP BY子句关联的工作表。
与HASH计划相关的工作文件。

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

跟踪标志-T1118在SQL Server 2000 SP3这是强迫SQL使用混合页分配一个循环算法加入。这种新算法与将tempdb部署在一组相同大小的文件之上的做法相关联,每个CPU对应一个,这样可以缓解争用。跟踪标志在SQL 2005/2008中仍然存在,尽管它不太可能需要。

关于这个神话的一切都非常BS。

  • 确实使用#temp表格会导致阻塞?不,在最坏的情况下,增加了SQL 2000及更早版本中负载下的争用,但与说它阻塞任何东西相去甚远。您必须首先进行测量,并看到情况如何,如果是这样,则部署修复措施(为每个CPU分配一个tempdb文件,使其等于大小,打开-T1118)。
  • 将select ... into #temp在选择期间阻塞某些东西?不是真的。
  • 是否将select ... ...变成#temp块,用于包含select的存储过程的持续时间?一定不行。只是阅读这一说法,我就笑了起来。

欲了解更多详情,还有这篇文章:Misconceptions around TF1118

+0

感谢您的信息! – 2009-08-20 13:59:33

+1

如果[select ... into #temp]处于事务中,在事务提交之前[select * from sysobjects]将在其他任何会话中被阻止。 – 2015-08-19 06:49:44

0

SELECT INTO #temp_table在声明的持续时间内在tempdb中保存shema锁,因为它正在完成的部分工作是创建表。这与首先​​使用CREATE TABLE #....创建表格然后运行基于集合的INSERT完全不同。 SELECT INTO确实比INSERT具有更多的优势,特别是如果数据库的恢复模型是简单日志或扩展日志,那么操作的记录会被最小化。

10

为什么不做以下几点?

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

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

INSERT #MyTable 
SELECT X, Y, Z 
FROM YourTable 
+1

针对利用系统漏洞的黑客+1。 – jp2code 2012-07-19 20:00:38

1

如果您在事务中创建#temp表,您可以获得阻塞。虽然这通常不被推荐,但我已经看到这样做了很多。

但是,由tempdb中的某些系统表导致的阻塞不会影响创建临时表的其他连接(可能除了2000版之前的SQL版本以外)。这意味着在tempdb上运行sp_spacesused将被阻塞,除非您将事务隔离级别设置为未提交读取。同时从SSMS查看tempdb上的属性将失败并超时,因为它正在使用读提交事务隔离级别。