INSERT SELECT 比 SELECT 慢

问题描述

我在函数一个简单部分遇到了一个大问题,它有一个返回类似 350 条记录的选择,我将结果插入到一个变量表中以供以后使用,但执行时间太长。

如果我只执行select,不执行insert,执行需要2秒。

DECLARE @CHEQUES2 TABLE (CardCode VARCHAR(20),Qtde Int,Total DECIMAL(16,2),Terceiro BIT,PRIMARY KEY (CardCode,Terceiro))

INSERT INTO @CHEQUES2 (CardCode,Qtde,Total,Terceiro)
SELECT CARDCODE,COUNT(Numero) Qtde,sum(VALOR) Total,EmTerceiro
  FROM [VW_CP_teste] CHEQUES
 WHERE STATUS = 0
 GROUP BY CARDCODE,EmTerceiro

执行耗时30多分钟,但仅select只需要2秒

知道发生了什么吗?

我尝试使用 cte、subselect、cursor,从变量表中删除主键,但没有解决

编辑:sql Server 2012,96GB RAM,2 Sockets Xeon 2630

Edit2:测试我知道如果我使用临时表或真实表,它会在 3 秒内执行。

Edit3:我所做的一切都很简单。此查询函数内部使用,之所以是函数,是因为它用于连接表/视图,并且在许多其他查询中使用,例如在 Crystal Reports 中,因此将其更改为存储过程将是一个问题。

功能不是新功能,问题是在我对 VW_CP_TESTE 进行了一些必要的更改并进行了更多连接之后才开始的。我知道问题从这里开始,但是对 VIEW 的整个搜索没有任何挣扎,只是将它与变量表一起使用的部分。它与变量表一起使用以获得性能,在使用之前“节省”一些资源。

解决方法

尽管您所做的一切看起来都很简单,但请尝试通过 #tempTableName 预选到 sql-server 临时表中。这些“#”临时表仅对当前会话/连接有效,并在连接完成后消失。如果您在存储过程中使用它,那么您将能够直接从中查询它。如果你仍然需要你的“声明”表实例,那么在 #temp... 之后插入一个类似

SELECT CARDCODE,COUNT(Numero) Qtde,sum(VALOR) Total,EmTerceiro
  into #myTempTable
  FROM [VW_CP_teste] CHEQUES
 WHERE STATUS = 0
 GROUP BY CARDCODE,EmTerceiro


DECLARE @CHEQUES2 TABLE (CardCode VARCHAR(20),Qtde Int,Total DECIMAL(16,2),Terceiro BIT,PRIMARY KEY (CardCode,Terceiro))

INSERT INTO @CHEQUES2 (CardCode,Qtde,Total,Terceiro)
   select CardCode,EmTerciro from #myTempTable

也许它在插入之前在某处进行聚合时窒息,所以拉到它自己的#temp 将解决这个问题。如果时间仍然有问题,请告诉我。

备选方案

此外,如果您的函数在您准备时返回某种临时表结果,则存储过程也可以这样做。我在一个应用程序中有许多存储过程,我传递了一些参数来应用于查询,并且存储过程对#temp 表进行了大量预查询,解析,排序,进行其他清理工作。最后,我只做了一个

select * from #myResultCrud

并返回整个集合。只是一个您可能没有考虑过的选项。

,

这似乎是我 2 天前遇到并问过的类似问题。

请查看这篇文章—— INSERT operation taking time for Table variable even for 0 rows

它通过使用临时表而不是表变量对我有用,但我知道您不能在这里使用临时表。

尝试使用我在帖子中提到的其他解决方法,即更改数据库兼容性级别。另外,您能否说出您的数据库的数据库兼容性级别。 您可以通过查询进行检查 -

SELECT COMPATIBILITY_LEVEL FROM sys.databases WHERE name = '{database name}';

并使用此查询进行更新 -

ALTER DATABASE {database name} SET COMPATIBILITY_LEVEL = 120;

根据我的经验,table 变量对于兼容性级别 的表现似乎非常糟糕