【问题标题】:Drop or not drop temporary tables in stored procedures删除或不删除存储过程中的临时表
【发布时间】:2018-03-01 02:20:31
【问题描述】:

我多次看到这个问题,但我无法得到令我满意的答案。基本上人们和书籍所说的是“虽然临时表在超出范围时会被删除,但您应该在不再需要它们时显式删除它们以减少服务器上的资源需求”。

我很清楚,当您在管理工作室工作并创建表时,在您关闭窗口或断开连接之前,您将为该表使用一些资源,从逻辑上讲,最好删除它们。

但是当您使用过程时,如果您想清理表格,很可能您会在它的真正结束时这样做(我不是在谈论当您真的不需要时立即丢弃表格的情况程序中的那个)。所以工作流程是这样的:

当你加入 SP 时:

  • SP 执行开始
  • 做一些事情
  • 删除表格
  • 执行结束

据我了解,当你不掉线时它怎么可能工作:

  • SP 执行开始
  • 做一些事情
  • 执行结束
  • 删除表格

这里有什么不同?我只能想象需要一些资源来识别临时表。还有其他想法吗?

更新:

我用 2 SP 进行了简单的测试:

create procedure test  as
begin
create table #temp (a int)
insert into #temp values (1);
drop table #temp;
end

另一个没有 drop 语句。我启用了用户统计并运行了测试:

declare @i int = 0;
 while @i < 10000
 begin
 exec test;
 SET @i= @i + 1;
 end

这就是我得到的(试验 1-3 在 SP 中丢弃表,4-6 不丢弃)

如图所示,当我不删除临时表时,所有统计数据都相同或略有下降。

更新2:

我第二次运行此测试,但现在调用了 100k,并且还添加了 SET NOCOUNT ON。这些是结果:

第二次运行确认,如果您不在 SP 中删除表,那么您实际上节省了一些用户时间,因为这是由其他一些内部进程完成的,但在用户时间之外。

【问题讨论】:

  • 你考虑过表变量吗? odetocode.com/articles/365.aspx有了这些你就不用担心丢了
  • 你也不需要需要来删除临时表。在正常情况下,两者都被取消范围(尽管临时表在语句级别,而临时表与当前 SPID 相关联)。不过,表变量还有其他一整套利弊清单。
  • 我的问题不是关于“打扰”,我的问题是关于将它们放入 SP 的好处,正如 MSDN 和其他书籍所建议的那样。 @user193655 我说的是#temp 表
  • 我从未见过有人建议在存储过程中显式删除它们。你有链接到 MSDN 上建议的位置吗?
  • 您的测试结果很有意义 - 显式 DROP 必须等待删除/缓存操作完成。 (尽管大型表可能会发生延迟删除)而在隐式情况下,proc 完成执行后可能会发生清理......

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


【解决方案1】:

您可以在 Paul White 的这篇文章中了解更多信息:Temporary Tables in Stored Procedures

创建和删除,不要

我将在下一篇文章中更详细地讨论这个问题,但 关键是 CREATE TABLE 和 DROP TABLE 不创建和删除 存储过程中的临时表,如果临时对象可以 缓存。 DROP 时将临时对象重命名为内部形式 TABLE 被执行,并在以下情况下重命名为相同的用户可见名称 下次执行时遇到 CREATE TABLE。此外,任何 在临时表上自动创建的统计信息也是 缓存。这意味着来自先前执行的统计信息仍然存在 下次调用该过程的时间。

【讨论】:

  • 虽然这是我学到的新东西,但直到在 SP 结束时删除表是否有任何性能/空间/等好处时都没有回答
  • 是的,它回答了。这意味着如果您在 sp 中删除或不删除临时表,则根本没有区别,因为无论如何它都会被缓存并且根本不会被删除
  • 但在这种情况下存在差异,因为您不在存储过程中执行实际语句,并且很可能它是在它之外以某种方式执行的。很可能这就是为什么在我的测试中不丢弃统计数据会稍微好一些
  • 对不起,我不明白你在说什么区别。在任何情况下,无论您是否正在删除,表都会被重命名和 chached,它会在您发出显式删除或退出 sp 时发生
  • 我的意思是实现了一些逻辑,然后您或外部进程执行“DROP”语句。我同意它并没有真正丢弃桌子,但是这张桌子仍然做了一些事情。因此,当您在 SP 中包含 drop 语句时,它是使用用户时间完成的,但是如果您不这样做,那么它将由另一个不影响用户时间的进程完成。我希望我的观点现在很清楚。 (参见 OP 中的 UPDATE 2 部分)
【解决方案2】:

从技术上讲,在您的 SPID 关闭后,本地范围的临时表(前面有一个标签的临时表)将自动退出范围。在某些非常奇怪的情况下,您会在某处缓存临时表定义,然后没有真正的方法将其删除。通常,当您有一个嵌套的存储过程调用并包含同名的临时表时,就会发生这种情况。

当你用完表后就开始删除它们是个好习惯,但除非发生意外情况,否则一旦 proc 完成,它们应该被取消作用域。

【讨论】:

  • 我更多的是询问性能问题,而不是没有任何嵌套的并发问题。
  • 明白了。 Drop 是一种廉价的声明,但不是没有开销的声明。我的猜测是,如果您尽可能多地调用该过程,则 drop 可能会为 proc 增加一个非零的时间量(将 !10 批总数除以 10000 次执行,意味着您大约每 0.6 次删除表秒。如果你真的很好奇,我会运行探查器跟踪,看看你一遍又一遍地调用过程的不同部分分配了多少时间。但这提出了一个很好的观点。大量procs,删除(甚至创建)临时表可能不是最划算的。
猜你喜欢
  • 1970-01-01
  • 2021-11-10
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多