是否可以将索引添加到临时表?创建#t和声明@t之间的区别是什么

Ist*_*tel 14 sql t-sql indexing temp-tables

我需要做一个非常复杂的查询.有一次,这个查询必须连接到一个不幸被编入索引的视图.此视图也是连接大表的复杂视图.

View的输出可以简化为:

PID (int), Kind (int), Date (date), D1,D2..DN
Run Code Online (Sandbox Code Playgroud)

其中PID和日期和种类字段不是唯一的(可能有多个行具有相同的pid,种类,日期组合),但是那些将用于连接的行如此

left join ComplexView mkcs on mkcs.PID=q4.PersonID and mkcs.Date=q4.date and mkcs.Kind=1
left join ComplexView mkcl on mkcl.PID=q4.PersonID and mkcl.Date=q4.date and mkcl.Kind=2
left join ComplexView mkco on mkco.PID=q4.PersonID and mkco.Date=q4.date and mkco.Kind=3
Run Code Online (Sandbox Code Playgroud)

现在,如果我这样做,查询的执行需要很长时间,因为复杂的视图运行了三次我假设,并且在其大量行中只有一些实际使用(例如,40000只有2000只是用过的)

我所做的是声明@temptable,并从ComplexView中插入@temptable select*,其中Date ... - 每次查询一次我只选择我将从我的ComplexView中使用的行,然后我加入这个@temptable.

这显着缩短了执行时间.

但是,我注意到,如果我在我的数据库中创建一个表,并在PID,Kind,Date(非唯一聚簇)上添加聚簇索引并从该表中获取数据,那么从该表执行delete*并插入到此复杂视图中的表需要几秒钟(3或4),然后在我的查询中使用此表(左连接三次)将查询时间从1分钟缩短到30秒!

所以,我的问题是,首先 - 是否可以在声明的@temptables上创建索引.然后 - 我看到人们谈论"创建#temptable"语法.也许这就是我需要的?我在哪里可以读到声明@temptable和create #temptable之间的区别?我应该如何使用我的查询?(此查询适用于MS Reporting Services报告,如果重要的话).

Ale*_* K. 7

#tablename是一个物理表,存储在tempdb服务器将在创建它的连接关闭时自动删除,@tablename是一个存储在内存中的表,并且在创建它的批处理/过程的生命周期中存在,就像本地变量一样.

您只能向#temp表中添加(非PK)索引.

create table #blah (fld int)
create nonclustered index idx on #blah (fld)
Run Code Online (Sandbox Code Playgroud)

  • 这是否意味着如果两个人同时运行查询,并且此查询使用临时表,他们将访问相同的 #tablename 但不同的 @tablenames,因此在脚本中使用 #tablename 进行临时查询是不安全的?换句话说,当两个查询同时运行时会发生什么,每个查询都有具有相同 #temptable 标识符的 create 语句?他们每个人都有自己的#temptable 还是他们都访问同一个表? (3认同)
  • @DanzaiVer链接来自删除的答案; http://www.sqlteam.com/article/optimizing-performance-indexes-on-temp-tables (2认同)

Bri*_*haw 6

这不是一个完整的答案,但 #table 将创建一个您需要删除的临时表,否则它将保留在您的数据库中。@table 是一个表变量,其持续时间不会超过您的脚本。

另外,我认为这篇文章将回答您问题的另一部分。

在表变量上创建索引

  • 服务器连接断开后,临时表将消失,并且仅在该连接的范围内。并不是说丢弃你不再需要的东西是一个坏习惯,它只是没有必要。 (14认同)
  • 其实是需要的。例如,当我在 sql Management Studio 中运行查询时,它不会关闭会话,因此 create 语句会给出一个错误,表明对象已经存在!所以我认为最好手动删除它。网络上的文章也提出了这一点。 (2认同)