毫无意义地使用临时表?

时间:2013-08-31 16:07:40

标签: sql tsql reporting-services temp-tables

我正在修复一年前设计的相当复杂的SSRS报告中的缺陷。从我收集的信息来看,编写报告的人 - 我们组织的承包商现在已经离开而且无法提问 - 几年前就学会了SQL并且没有及时了解它 - 他的代码充满了过时和不好的做法,例如加入WHERE子句,按列号而不是列名排序,以及始终使用临时表而不是子查询或CTE。作为SQL的新手(不到一年的经验),我总是试图弄清楚我遇到的一些奇怪的编码的目的,并了解它使用的任何过时技术的历史。这是我无法弄清楚的 - 我正在使用的报告的存储过程在使用数据之前将所有内容选择到临时表中。如果编码器在三列50行查找表上需要两列,他将首先将这两列选择到临时表中。即使对于最终的SELECT,他总是首先选择一个临时表,然后执行SELECT *来访问数据。我以前没见过这个,对我来说似乎毫无意义。为什么不直接访问数据?在SQL的历史中,有没有或曾经有过这样做的任何目的,还是只是简单的错误编码?

2 个答案:

答案 0 :(得分:2)

我会猜测这个 - 使用临时表的原因。请注意,下面提到的推理只是一些观点,可能不一定是真正的原因。可能只是个人不知道编写SQL的正确方法。但是,以下是使用临时表的一些原因:

  1. 模拟视图 - 例如他在50行表中只选择3列中的2列,这意味着他实际上只想在这两列中找到数据的逻辑视图 - 这可以通过CTE轻松完成。
  2. 隔离数据更改 - 他希望确保他始终处理数据的副本,以便与基表的数据更改隔离(实质上,这将成为快照的主表)也不想让他的查询对基表进行意外修改。
  3. 性能 - 可能是他要查询的原始表格没有用于搜索和排序的错误构建索引 - 他碰巧通过构建临时表来补偿这一点,其中索引构建在查询中所需的列上,这样就可以了帮助他实现更快的查询处理。它还为他提供了一种方法来阻止对主表结构的任何更改(这会减慢其他操作,如插入和删除)。
  4. 话虽如此,重要的是要注意这些都是错误的编码实践。始终建议使用SQL Server提供的设备(如CTE,Views等)来处理数据库中的数据。当您想要在插入表之前预处理数据时,临时表是不错的选择,并且在数据库之外这样做是很昂贵的(例如想象一个数据处理系统从转储文件中读取数据并将它们插入到数据库中包含数百万行的主表。转储表可能包含已经存在于表中的重复数据,因此我们不想插入这样的行。在这种情况下,数据处理系统可以转储候选行进入临时表,然后使用SQL服务器的强大设置操作,以过滤掉重复的行。)

答案 1 :(得分:1)

根据你的描述,我会称之为糟糕的编码。

在某些情况下,我可以想象按照您的描述进行选择。大多数属于“表需要很长时间才能读取”或“表中的统计数据无法被优化程序有效使用”的类别。一个原因可能是该表位于不同服务器上的数据库中。拥有本地副本通常会使查询更多更有效。或者,“表格”实际上可能是需要很长时间才能处理的视图。

另一种情况是表格上有很多更新,并且出于某种原因需要快照以获得一系列报告。您可能需要在不同报告之间保持一致性,因此将数据放入临时表可以保证这一点。

但总的来说,你永远不会这样做。如果您有一个小型参考表,则只需将其包含在from子句中并访问所需的列。 SQL Server可以很好地优化对表的访问,并将处理仅限于所需的列。将事物放在临时表中会阻碍优化器 - 这通常(但不总是)是一件坏事。