【问题标题】:Persistent temp tables in SQL?SQL中的持久临时表?
【发布时间】:2010-10-25 03:51:21
【问题描述】:

在 MS-SQL 中是否可以有一个“持久”临时表?我的意思是我目前有一个后台任务,它生成一个全局临时表,它被各种其他任务使用(这就是我将它设为全局的原因)。不幸的是,如果该表未被使用,它会被 SQL 自动删除——这由我的系统优雅地处理,因为它只是将它排队等待再次重建,但理想情况下我希望它每天只构建一次。所以,理想情况下,我可以设置一些超时参数,比如“如果 1 小时内没有任何东西触及它,则删除”。

我真的不希望在我现有的数据库中使用它,因为它会导致更多与管理数据库相关的麻烦(碎片、日志增长等),因为它实际上是汇总数据,仅在 24 小时内有用,并且占用超过 1 GB 的 HD 空间。

在最坏的情况下,我的计划是在与 tempdb 相同的驱动器上创建另一个 DB,将其命名为 PseudoTempDB,然后自己处理删除。

任何见解都将不胜感激!

【问题讨论】:

  • 选择 B 计划,自己管理生命周期,仅 SQL Server 无法满足您的要求。
  • 我发现这篇文章可能会有所帮助:stackoverflow.com/questions/27835/…
  • kekoav,我的理解是表变量的工作方式与临时表非常相似(就持久性而言)。所以我的假设是一旦我停止访问它,表变量就会消失(就像临时表一样)。
  • 标记 Kekoa 分享的帖子 stackoverflow.com/a/27849/77198 指出带有双哈希前缀的表(例如 ##TempTableName)将保留在 tempdb 中。即使在引用或创建它的对象超出范围之后。删除的方法是显式删除表,或者重启数据库实例
  • @BobF for global temp table ## 如果表处于空闲状态并且创建的 sql 实例被销毁,那么它们仅在同一个 sql 实例中持久存在,那么这些表也会被删除。如果我错了,请纠正我

标签: sql sql-server tempdb


【解决方案1】:

如果您将表创建为 tempdb.dbo.TempTable,它不会被删除,直到:

a - SQL Server 已重新启动

b - 你明确删除它

如果您希望它始终可用,您可以在模型中创建该表,以便在重新启动期间将其复制到 tempdb(但它也将在您之后创建的任何新数据库上创建,因此您可以必须手动删除)或使用启动存储过程来创建它。但是,没有办法通过重新启动来持久化数据。

【讨论】:

  • 很有趣,所以如果您使用 TempDB 作为数据库创建它,而不是在 # 或 ## 之前添加,那么它会在重新启动之前变得有效(当 tempdb 无论如何都被转储时)?这正是我所追求的——如果它不存在,我可以重新创建它。
  • @Mark,你能否确认一下 LeoPasta 所说的是否正确?
  • @Mark 这得到证实了吗?
【解决方案2】:

我会采用您的计划 B,“在与 tempdb 相同的驱动器上创建另一个数据库,将其称为 PseudoTempDB,然后自己处理删除。”

【讨论】:

    【解决方案3】:

    创建一个永久表怎么样?说,MyTable。每 24 小时刷新一次数据,如下所示:

    1. 创建一个新表 MyTableNew 并填充它
    2. 在事务中,删除 MyTable,并使用 rename_object 将 MyTableNew 重命名为 MyTable

    这样,您每天都在重新创建表格。

    如果您担心日志文件,请将表存储在不同的数据库中并将其设置为恢复模式:简单。

    【讨论】:

    • 这基本上就是我上面概述的 - 唯一的区别是您建议在同一个数据库中执行它。我当然可以将它放在同一个数据库中,但由于它不是有用的长期数据,我不希望它在数据库的备份中(并且不想开始使用排除使事情复杂化)。
    • @Mark 虽然我确实认为“不同的数据库并将其设置为恢复模式:简单”有优点,因为它允许您使用多租户 SQL Server 而不必担心@987654321 中的名称冲突@.
    【解决方案4】:

    我不得不承认对这个问题做了双重考虑:“持久”和“临时”通常不会一起出现!开箱即用的想法怎么样?也许您的后台任务可以定期运行一个简单的查询,以防止 SQL 将表标记为未使用。这样一来,您就可以直接控制创建和拆除。

    【讨论】:

    • 是的,有点二分法——我只想要一个更大的窗口来存放我的“临时”数据。 :) 实际上,您甚至不需要在后台运行查询,只要您打开了一个对它运行一次查询的连接,它就会保留下来。作为一个黑客,这就是我目前正在做的事情,但如果连接由于某种原因断开,那么它需要重建所有内容,所以它不像我的计划 B 那样干净。
    • 这很容易做到。如果临时表不包含太多行,则 select count(*) from foo 会这样做。
    【解决方案5】:

    在处理现有所有主要 RDBMS 的 20 年经验之后,我只能建议您考虑以下几点:

    1. 注意矛盾的概念:“持久”和“临时”是完全相反的。选择一个,并且只选择一个。

    2. 您不会对您的数据库有任何帮助,以手动、半永久性、用户驱动的方式将数据写入临时数据库。为此目的,普通表空间(即用户)已经存在。临时数据库是用于临时的。

    3. 如果您已经知道这样的表将被永久使用(“每日”是永久的),那么将其创建为用户数据库/模式上的普通表。

    4. 每次您删除并重新创建同一个表时,您都在分割整个数据库。并且永远不会给 DB 引擎优化器机会来帮助您进行任何形式的粗略优化。相反,请尝试截断它。您的回滚段将感谢您的小幅缓解,并且当您第二天再次重新填充它时,可能仍会分配磁盘空间。您可以通过单独为该表指定单独的表空间和数据文件来强制执行所需的行为。

    5. 最后,更重要的是:不要再为了区区 1 GB 的数据而折磨您和您的数据库引擎。为了节省 0.02 美分的硬件真实状态,您正在浪费 CPU、I/O 周期、增加延迟、碎片等。谈论穿着燕尾服掉到地板上捡起棕色美分。 ?

    【讨论】:

      猜你喜欢
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多