SQL server2008 临时表tempdb如何自动释放存储空间
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL server2008 临时表tempdb如何自动释放存储空间相关的知识,希望对你有一定的参考价值。
tempdb不能设置自动收缩,提示5058错误,如何设置自动收缩,手动收缩不能收缩到原始8M,而是从2.5G收缩到了1G左右、我该如何收缩到原始内存,以及如何设置自动收缩
在不影响服务器性能的情况下如何自动释放存储空间,不能重启服务。这是首要前提。
drop table #Tmp --删除临时表#Tmpcreate table #Tmp --创建临时表#Tmp( ID int IDENTITY (1,1) not null, --创建列ID,并且每次新增一条记录就会加1 WokNo varchar(50), primary key (ID) --定义ID为临时表#Tmp的主键 );Select * from #Tmp --查询临时表的数据truncate table #Tmp --清空临时表的所有数据和约束
相关例子:
Declare @Wokno Varchar(500) --用来记录职工号Declare @Str NVarchar(4000) --用来存放查询语句Declare @Count int --求出总记录数 Declare @i intSet @i = 0 Select @Count = Count(Distinct(Wokno)) from #TmpWhile @i < @Count Begin Set @Str = 'Select top 1 @Wokno = WokNo from #Tmp Where id not in (Select top ' + Str(@i) + 'id from #Tmp)' Exec Sp_ExecuteSql @Str,N'@WokNo Varchar(500) OutPut',@WokNo Output Select @WokNo,@i --一行一行把职工号显示出来 Set @i = @i + 1 End临时表可以创建本地和全局临时表。本地临时表仅在当前会话中可见;全局临时表在所有会话中都可见。
本地临时表的名称前面有一个编号符 (#table_name),而全局临时表的名称前面有两个编号符 (##table_name)。
SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的名称引用临时表:
CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)INSERT INTO #MyTempTable VALUES (1)
如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则 SQL Server 必须能够区分由不同用户创建的表。为此,SQL Server 在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdb 数据库的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的表名 table_name 不能超过 116 个字符。
除非使用 DROP TABLE 语句显式除去临时表,否则临时表将在退出其作用域时由系统自动除去:
当存储过程完成时,将自动除去在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。
所有其它本地临时表在当前会话结束时自动除去。
全局临时表在创建此表的会话结束且其它任务停止对其引用时自动除去。任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。换言之,当创建全局临时表的会话结束时,最后一条引用此表的 Transact-SQL 语句完成后,将自动除去此表。 在存储过程或触发器中创建的本地临时表与在调用存储过程或触发器之前创建的同名临时表不同。如果查询引用临时表,而同时有两个同名的临时表,则不定义针对哪个表解析该查询。嵌套存储过程同样可以创建与调用它的存储过程所创建的临时表同名的临时表。嵌套存储过程中对表名的所有引用都被解释为是针对该嵌套过程所创建的表,例如:
CREATE PROCEDURE Test2ASCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (2)SELECT Test2Col = x FROM #tGOCREATE PROCEDURE Test1ASCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (1)SELECT Test1Col = x FROM #tEXEC Test2GOCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (99)GOEXEC Test1GO
下面是结果集:
(1 row(s) affected)
Test1Col ----------- 1
(1 row(s) affected)
Test2Col ----------- 2
当创建本地或全局临时表时,CREATE TABLE 语法支持除 FOREIGN KEY 约束以外的其它所有约束定义。如果在临时表中指定 FOREIGN KEY 约束,该语句将返回警告信息,指出此约束已被忽略,表仍会创建,但不具有 FOREIGN KEY 约束。在 FOREIGN KEY 约束中不能引用临时表。
考虑使用表变量而不使用临时表。当需要在临时表上显式地创建索引时,或多个存储过程或函数需要使用表值时,临时表很有用。通常,表变量提供更有效的查询处理。 参考技术A 重启 SQL 服务 时就会重新建立 tempdb,
你这样设置自动收缩,还不如重启服务,,,追问
不能重启服务。系统在被使用
追答我们这边一般都是定期晚上凌晨重启下的,,你要是非要人工不起服务,有点麻烦,给你发个地址,你去看看吧,,,
http://support.microsoft.com/kb/307487/zh-cn
SQL Server SELECT INTO 和临时表阻塞
【中文标题】SQL Server SELECT INTO 和临时表阻塞【英文标题】:SQL Server SELECT INTO and Blocking With Temp Tables 【发布时间】:2010-11-21 02:53:45 【问题描述】:所以,最近一位 DBA 试图告诉我们,我们不能使用以下语法
SELECT X, Y, Z
INTO #MyTable
FROM YourTable
在我们的环境中创建临时表,因为该语法会在存储过程执行期间导致 TempDB 锁定。现在,我发现了许多详细说明临时表如何工作、执行范围、清理等的内容。但在我的一生中,我看不到任何关于阻塞的东西,因为它们的使用。
我们正在努力寻找证据证明我们不应该为所有临时表执行 CREATE TABLE #MyTable...,但双方都找不到证据。我正在寻找人们的任何见解。
附加信息
目前使用 SQL Server 2005,很快将使用 SQL Server 2008(企业版)
【问题讨论】:
【参考方案1】:虽然 SELECT INTO 已解决阻止 tempdb 的问题,但我在编写此类代码时要小心,因为某些系统表确实被阻止了。
参考: http://www.sqlservercentral.com/Forums/Topic1642797-2799-1.aspx
【讨论】:
【参考方案2】:SELECT INTO #temp_table
在语句执行期间在 tempdb 中持有一个 shema 锁,因为它完成的部分工作是创建表。这与首先使用CREATE TABLE #....
创建表然后运行基于集合的INSERT 根本不同。 SELECT INTO
确实比 INSERT
有优势,特别是如果数据库的恢复模型是简单或批量日志,则该操作的日志记录最少。
【讨论】:
【参考方案3】:如果您在事务中创建#temp 表,您可能会遇到阻塞。虽然通常不建议这样做,但我已经看到很多这样做了。
但是,这导致的阻塞发生在 tempdb 中的某些系统表上,这些系统表不会影响其他连接创建临时表(可能除了 2000 年之前的 SQL 版本?)。这确实意味着在 tempdb 上运行 sp_spacesused 将阻塞,除非您将事务隔离级别设置为未提交读取。同样,从 SSMS 查看 tempdb 上的属性也会失败并超时,因为它使用的是已提交的读取事务隔离级别。
【讨论】:
【参考方案4】:为什么不做以下事情?
SELECT X, Y, Z
INTO #MyTable
FROM YourTable
WHERE 1 = 2
该语句将立即运行 - 创建您的临时表并避免任何可能的锁定。然后你可以像往常一样插入它:
INSERT #MyTable
SELECT X, Y, Z
FROM YourTable
【讨论】:
【参考方案5】:这可能会漂浮很长时间,喂饱各种“顾问”的口袋。像所有的神话一样,它有一个真理的核心和大量的废话。
事实: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 对混合页面分配使用循环算法。这种新算法与将 tempdb 部署在一组大小相等的文件(每个 CPU 一个)之上的做法相关联时,将减轻争用。跟踪标志仍然存在于 SQL 2005/2008 中,尽管它不太可能被需要。
关于这个神话的其他一切都非常荒谬。
使用#temp 表会导致阻塞吗?不会。在 SQL 2000 及更早版本中,它增加了负载下的争用,但这与说它阻止任何东西相去甚远。您必须先进行测量,看看是否是这种情况,如果是,请部署补救措施(为每个 CPU 分配一个 tempdb 文件,使它们大小相等,打开 -T1118).. select ... into #temp 在选择期间是否会阻塞某些内容?不是。 在包含选择的存储过程期间,select ... into #temp 是否会阻塞某些内容?一定不行。只是读到那个声明,我就笑了。更多详情,有这篇文章:Misconceptions around TF1118。
【讨论】:
如果 [select ... into #temp] 在事务中,在事务提交之前,[select * from sysobjects] 将在任何其他会话中被阻塞。【参考方案6】:这个建议一直在for a long time附近流传:
SQL Server 6.5 中的瓶颈
许多人使用 SELECT...INTO 查询 创建一个临时表,一些东西 像这样:
SELECT * INTO #TempTable FROM 源表
虽然这有效,但它会创建锁 针对 tempdb 数据库 SELECT 语句的持续时间 (如果你在拖网,很长一段时间 通过源中的大量数据 表,如果 SELECT...INTO 在开头 运行时间更长的显式事务) 当锁就位时,没有其他 用户可以创建临时表。这 瓶颈的实际位置是 锁定 tempdb 系统表。在以后 SQL Server 的版本,锁定 模型变了,问题是 避免。
幸运的是,这只是 SQL 6.5 的问题。它已在 7.0 及更高版本中修复。
【讨论】:
您能否使用 SQL 的新功能更新您的答案,因为您的答案首先出现在 Google 搜索中,并且它应该对最新版本有效。 TIA :) @RajShah 什么过时了?除非更高版本再次破坏它,否则我无法想象“它已在 7.0 及更高版本中修复”。是一个将过时的声明。 (而且“对于 6.5 来说是个问题”当然不能)。【参考方案7】:如果这是真的,那么 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
当然,您应该先评估是否需要临时表和副本。尽管如果查询足够复杂以至于使用临时表更具可读性,那么它也可能足够复杂以至于值得使用临时表。
【讨论】:
【参考方案8】:我会说缺乏锁定证明意味着没有锁定,这是你的证明。为什么创建临时表的方法(CREATE 或 SELECT ... INTO)会影响锁定 TempDB?
【讨论】:
这也是我们的想法和论点......但他们坚持认为使用 SELECT INTO 会导致存储过程期间的阻塞。 我想知道为什么临时表被锁定也是一个问题。如果是全局临时表,那就另当别论了。 @rexem:OP 的 DBA 并不是说临时表已锁定,而是说 TempDB、所有临时表的位置和其他临时存储已锁定。不知道DBA是否正确,我会听从更聪明的人的意见。以上是关于SQL server2008 临时表tempdb如何自动释放存储空间的主要内容,如果未能解决你的问题,请参考以下文章