将表变量更改为临时表

时间:2016-02-08 08:39:57

标签: sql-server tsql sql-server-2012

我有几年前编写的某个存储过程。它使用表变量。在代码内部:

declare @OpportunityVS3 as SF_OpportunityMerge
insert @TableVariable select * from /*...*/

这是一个每五分钟运行一次的工作。过去曾经没有任何问题,因为select过去常常收集大约10到1000条记录......但现在有时候,select会尝试插入一百万条记录。

鉴于此问题,我认为我被迫将@TableVariable更改为#TempTable。你怎么看?我还有其他选择吗?

在SP结束时,它将变量传递给另一个SP:

exec [dbo].[SF_MergeOpportunity] @OpportunityVS3, @LastUpdateDate

我想我必须在同一个存储过程中编写它,因为临时表不能传递,对吧?

以下是正在使用的@TableVariable的定义以及我必须更改的代码:

declare @OpportunityVS3 as SF_OpportunityMerge

insert  @OpportunityVS3 select Opportunity_id, Salesforce_id, AccountId, Age__c,  
-- (continues)

merge [BU2].[dbo].[Salesforce_Opportunity] as TARGET 
using ( select  Opportunity_id, 
    Salesforce_id, 
    AccountId, 
    Age__c, 
    Amount, 
    Bill99Amount__c, 
    BJ_Marketing__c
    -- (continues)
    from @OpportunityVS3 ) as SOURCE on (TARGET.Opportunity_id = SOURCE.Opportunity_id) 

exec [dbo].[SF_MergeOpportunity] @OpportunityVS3, @LastUpdateDate

[![在此处输入图像说明] [1]] [1]

[![在此处输入图像说明] [2]] [2]

1 个答案:

答案 0 :(得分:0)

您可以尝试不改变工作方式:

  • 通过使用TABLE变量
  • 在查询中指定OPTION(RECOMPILE),强制编译器将TABLE变量的基数考虑在内
  • UNIQUE INDEX变量
  • 提供合适的PRIMARY KEYTABLE

TABLE变量的缺点是没有与它们相关的统计数据。当SQL编译器可以将统计信息考虑在内时,它将产生更好的执行计划。因此,当您切换到临时表时,可以显着提高性能,因为这些执行具有统计信息。

当您切换到临时表时,您将不再再将TABLE变量传递给存储过程。然后,您的存储过程将使用它事先知道存在的临时表写入 - 即在执行存储过程之前创建。

您可以编写存储过程,就像临时表是普通表一样。当您使用临时表编写存储过程时,SQL Server管理工作室将以红色突出显示某些部分,因此看起来存储过程中存在错误。但是如果语法正确,创建/修改存储过程就可以了。

关于TABLE变量和临时表之间的差异,请阅读此excellent essay,了解使用情况如何影响性能。特别是主题无列统计索引