这是一个悬而未决的问题,但我真的很想听听别人的意见。
我很少使用显式声明的临时表(表变量或常规#tmp表),因为我认为不这样做会导致更简洁,可读和可调试的T-SQL。我还认为SQL可以比我在需要时使用临时存储(例如在查询中使用派生表时)做得更好。
唯一的例外是当数据库不是典型的关系数据库而是星形或雪花模式时。我知道最好先将过滤器应用于事实表,然后使用生成的临时表从维度中获取值。
这是普遍意见还是有人反对意见?
答案 0 :(得分:14)
临时表对于复杂的批处理过程(如报表或ETL作业)最有用。通常,您希望在事务性应用程序中很少使用它们。
如果您正在使用涉及多个大型表(可能是报表)的连接进行复杂查询,那么查询优化器实际上可能无法在一次命中中对此进行优化,因此临时表在此处成为胜利 - 它们会分解查询进入一系列更简单的方法,使查询优化器更少有机会搞砸计划。有时您的操作根本无法在单个SQL语句中完成,因此需要多个处理步骤才能完成工作。我们再次讨论更复杂的操作。
您还可以为中间结果创建临时表,然后对表进行索引,甚至可能在其上放置聚簇索引以优化后续查询。这也可能是一种快速而肮脏的方法,可以在不允许向数据库模式添加索引的系统上优化报表查询。 SELECT INTO对于此类操作很有用,因为它记录最少(因此速度很快),并且不需要对齐select和insert的列。
其他原因可能包括使用CROSS APPLY和xpath查询从XML字段中提取数据。通常,将其提取到临时表中然后处理临时表会更有效。对于某些任务,它们也比CTE快得多,因为它们实现了查询结果而不是重新评估查询。
需要注意的一点是,临时表与查询引擎用于存储中间连接结果的结构完全相同,因此使用它们不会有性能损失。临时表还允许使用set操作进行多阶段任务,并且在T-SQL代码中几乎(几乎不是)几乎不需要游标。
'Code Smell'是一种夸大其词但如果我看到很多涉及临时表的简单操作,我会想知道发生了什么。
答案 1 :(得分:5)
这实际上取决于你在做什么。我通常会尽量避免它们,但有时你需要做一些复杂的事情,需要多个步骤。通常这超出了从表格中选择的简单方法。像其他任何东西一样,它是一个你必须知道何时使用的工具。
我同意你的观点,我通常会让db处理幕后的东西,但有时候它的优化是关闭的,你必须亲自去做。
答案 2 :(得分:3)
我将临时表视为一种SQL代码气味,仅作为最后的手段使用。如果您在获得最终结果集之前必须缓存数据,那么它通常会向我指示错误的数据库设计。
答案 3 :(得分:3)
临时表肯定有适当的用途,如果使用正确,它们就不是代码味道。关于它们的一个好处是它们存在于tempdb中,通常设置为简单恢复模型。这意味着如果你正在使用临时表来获得它们的好处(主要是批量操作),那么与生成数据库中的表相同的操作相比,你生成的日志量最少,这可能是在完全恢复模型中。
如果正如另一张海报建议的那样,您的生产数据库位于良好的硬件上,但您的tempdb不是,请让您的DBA移动它。 SQL Server本身使用tempdb来处理您的查询,因此tempdb具有高性能的家庭非常重要。
表变量完全是一个不同的生物。他们只活在记忆中。对他们来说一个很好的用途是,如果你有一个函数,你需要使用CROSS APPLY调用查询中的每一行。如果该功能很昂贵,但是您可以从中获得的结果数量很少,那么通过预先计算所有可能调用的结果(或者可能是对数据集的所有可能调用)并将其存储在表变量,然后加入到该表变量而不是使用CROSS APPLY。
答案 4 :(得分:0)
我也避免使用临时表。据我所知,MS SQL Server上的临时表始终位于master数据库的文件组中。这意味着,虽然您的生产应用程序表很可能是在一些昂贵的高性能RAID设置上,但您的临时表位于安装MS SQL Server的位置,这很可能位于Program Files目录下的C:驱动器上。
答案 5 :(得分:0)
当您有一个需要检索一次并在后续语句中反复使用的数据集时,也很有用。
使这些长批处理过程更具可读性(有时这比性能更重要)。