5

这是一个悬而未决的问题,但我真的很想听听人们的意见。

我很少使用显式声明的临时表(表变量或常规#tmp 表),因为我相信不这样做会导致更简洁、可读和可调试的 T-SQL。我还认为,在需要时(例如在查询中使用派生表时),SQL 可以比我更好地利用临时存储。

唯一的例外是当数据库不是典型的关系数据库而是星型或雪花模式时。我知道最好先将过滤器应用于事实表,然后使用生成的临时表从您的维度中获取值。

这是普遍观点还是有人持反对意见?

4

6 回答 6

14

临时表对于报告或 ETL 作业等复杂的批处理过程最有用。通常,您希望在事务应用程序中很少使用它们。

如果您正在使用涉及多个大表(可能用于报告)的连接进行复杂查询,则查询优化器实际上可能无法一次优化,因此临时表在这里成为一种胜利 - 它们将查询分解为一系列更简单的那些给查询优化器更少的机会来搞砸计划。有时您的操作根本无法在单个 SQL 语句中完成,因此需要多个处理步骤才能完成这项工作。同样,我们在这里讨论更复杂的操作。

您还可以为中间结果创建一个临时表,然后对该表进行索引,甚至可能在其上放置一个聚集索引以优化后续查询。在不允许将索引添加到数据库模式的系统上,这也可能是一种快速而肮脏的优化报表查询的方法。SELECT INTO 对于这种类型的操作很有用,因为它的日志记录最少(因此速度很快)并且不需要对齐选择和插入的列。

其他原因可能包括使用 CROSS APPLY 和 xpath 查询从 XML 字段中提取数据。通常,将其提取到临时表中然后在临时表上工作会更有效。对于某些任务,它们也比 CTE 快得多,因为它们实现了查询结果而不是重新评估查询。

需要注意的一点是,临时表与查询引擎用于存储中间连接结果的结构完全相同,因此使用它们不会降低性能。临时表还允许使用集合操作进行多阶段任务,并使游标在 T-SQL 代码中几乎(不是完全但几乎)不必要。

'Code Smell' 言过其实,但如果我看到很多涉及临时表的简单操作,我会想知道发生了什么。

于 2009-01-15T15:38:46.040 回答
5

这真的取决于你在做什么。我通常会尽量避免它们,但有时你需要做一些需要多个步骤的复杂操作。通常,这远远超出了从表中选择的简单内容。像其他任何东西一样,它是您必须知道何时使用的工具。

我同意你的观点,我通常让数据库在幕后处理事情,但有时它的优化已关闭,你必须进去手动完成。

于 2009-01-15T15:33:09.780 回答
3

我将临时表视为一种 SQL 代码气味,只能作为最后的手段使用。如果您必须在获得最终结果集之前缓存数据,那么这通常表明我的数据库设计不佳。

于 2009-01-15T15:16:30.127 回答
3

临时表当然有适当的用途,如果使用得当,它们不是代码味道。它们的优点之一是它们位于 tempdb 中,它通常设置为简单恢复模式。这意味着,如果您将临时表用于它们的优点(主要是批量操作),那么与相同操作在生产数据库中的表上执行的操作相比,您生成的日志量最少,这可能是在完全恢复模式。

如果,正如另一张海报所建议的那样,您的生产数据库在良好的硬件上,但您的 tempdb 不是,请让您的 DBA 移动它。SQL Server 本身大量使用 tempdb 来处理您的查询,因此 tempdb 拥有一个高性能的主页非常重要。

表变量是完全不同的生物。他们只活在记忆中。它们的一个很好的用途是,如果您有一个函数,您需要使用 CROSS APPLY 为查询中的每一行调用该函数。如果该函数很昂贵,但您可以从中获得的不同结果的数量很少,那么您可能会通过预先计算所有可能调用的结果(或者可能对您的数据集的所有可能调用)的结果并将其存储在表变量,然后加入该表变量而不是使用 CROSS APPLY。

于 2011-02-26T00:24:29.977 回答
0

我也避免使用临时表。据我了解,MS SQL Server 上的临时表始终位于主数据库的文件组中。这意味着,虽然您的生产应用程序表很可能位于一些昂贵的高性能 RAID 设置上,但您的临时表位于安装 MS SQL Server 的任何位置,很可能位于 C: 驱动器的 Program Files 目录下。

于 2009-01-23T20:38:29.897 回答
0

当您有一个需要检索一次并在后续语句中反复使用的数据集时也很有用。

使这些长批处理过程更具可读性(有时这比性能更重要)。

于 2013-11-21T18:30:24.623 回答