SQL Server 中的临时表使用
Posted
技术标签:
【中文标题】SQL Server 中的临时表使用【英文标题】:Temporary Table Usage in SQL Server 【发布时间】:2009-01-15 15:15:16 【问题描述】:这是一个有点悬而未决的问题,但我真的很想听听人们的意见。
我很少使用显式声明的临时表(表变量或常规#tmp 表),因为我相信不这样做会导致更简洁、可读和可调试的 T-SQL。我还认为,在需要时(例如在查询中使用派生表时),SQL 可以比我更好地利用临时存储。
唯一的例外是当数据库不是典型的关系数据库而是星形或雪花模式时。我知道最好先将过滤器应用于事实表,然后使用生成的临时表从您的维度中获取值。
这是普遍看法还是有人持反对意见?
【问题讨论】:
【参考方案1】:临时表对于报表或 ETL 作业等复杂的批处理过程最有用。通常,您希望在事务应用程序中很少使用它们。
如果您正在使用涉及多个大型表(可能是报告)的连接进行复杂查询,则查询优化器实际上可能无法一键优化,因此临时表在这里成为一种胜利 - 它们分解查询到一系列更简单的,让查询优化器更少的机会搞砸计划。有时您的操作根本无法在单个 SQL 语句中完成,因此需要多个处理步骤才能完成这项工作。同样,我们在这里讨论的是更复杂的操作。
您还可以为中间结果创建一个临时表,然后对该表进行索引,甚至可能在其上放置一个聚集索引以优化后续查询。在不允许将索引添加到数据库模式的系统上,这也可能是一种快速而肮脏的优化报表查询的方法。 SELECT INTO 对于这种类型的操作很有用,因为它的日志记录最少(因此速度很快),并且不需要对齐 select 和 insert 的列。
其他原因可能包括使用 CROSS APPLY 和 xpath 查询从 XML 字段中提取数据。通常,将其提取到临时表中然后在临时表上工作会更有效。对于某些任务,它们也比 CTE 快得多,因为它们实现了查询结果而不是重新评估查询。
需要注意的一点是,临时表与查询引擎用于存储中间连接结果的结构完全相同,因此使用它们不会降低性能。临时表还允许使用集合操作进行多阶段任务,并使游标在 T-SQL 代码中几乎(不是完全但几乎)不必要。
'Code Smell' 言过其实,但如果我看到很多涉及临时表的简单操作,我会想知道发生了什么。
【讨论】:
【参考方案2】:这真的取决于你在做什么。我通常会尽量避免它们,但有时你需要做一些复杂的事情,需要多个步骤。通常,这远远超出了从表中选择的简单内容。像其他任何东西一样,它是您必须知道何时使用的工具。
我同意你的观点,我通常让数据库在幕后处理事情,但有时它的优化已关闭,你必须进去手动完成。
【讨论】:
你是对的。当复杂而直接的 SQL 不执行而临时表执行时,你会怎么做? 在中间层做复杂的事情。 你的意思是要聚合数百万条记录吗?【参考方案3】:我认为临时表是一种 SQL 代码气味,只能作为最后的手段使用。如果您必须在获得最终结果集之前缓存数据,那么这通常表明我的数据库设计不佳。
【讨论】:
这也是我的看法,但我只是想知道我是不是一个势利小人! 需要注意的一点是,糟糕的数据库设计比您想象的要普遍得多。如果您想体验处理不良数据库设计后果的乐趣,请尝试在数据仓库工作几年。【参考方案4】:临时表当然有适当的用途,如果使用得当,它们不会产生代码异味。它们的优点之一是它们存在于 tempdb 中,它通常设置为简单恢复模式。这意味着,如果您将临时表用于它们的优点(主要是批量操作),那么与相同操作在生产数据库中的表上执行的操作相比,您生成的日志量最少,这可能是在完全恢复模式中。
如果正如另一张海报所建议的那样,您的生产数据库在良好的硬件上,但您的 tempdb 不是,请让您的 DBA 移动它。 SQL Server 本身大量使用 tempdb 来处理您的查询,因此 tempdb 拥有一个高性能的 home 非常重要。
表变量是完全不同的生物。他们只活在记忆中。它们的一个很好的用途是,如果您有一个函数,您需要使用 CROSS APPLY 为查询中的每一行调用该函数。如果该函数很昂贵,但您可以从中获得的不同结果的数量很少,那么您可能会通过预先计算所有可能调用(或者可能对您的数据集的所有可能调用)的结果并将其存储在表变量,然后加入该表变量而不是使用 CROSS APPLY。
【讨论】:
+1 很好的答案,但这条线不是真的:“表变量是完全不同的生物。它们只存在于内存中”这是一个神话。它们也在 tempdb 中分配空间。 @Martin - 完全正确!通过Inside Microsoft SQL Server 2008:T-SQL 编程验证,感谢告知!【参考方案5】:我也避免使用临时表。据我了解,MS SQL Server 上的临时表始终位于主数据库的文件组中。这意味着,虽然您的生产应用程序表很可能位于一些昂贵的高性能 RAID 设置上,但您的临时表位于安装 MS SQL Server 的任何位置,很可能位于 C: 驱动器的 Program Files 目录下。
【讨论】:
【参考方案6】:当您有一个需要检索一次并在后续语句中反复使用的数据集时也很有用。
使这些长批处理过程更具可读性(有时这比性能更重要)。
【讨论】:
以上是关于SQL Server 中的临时表使用的主要内容,如果未能解决你的问题,请参考以下文章