2013-03-28 14 views
0

我有一段动态的SQL。大约需要4分钟。如果我改用静态SQL,大约需要20秒。有没有办法在你的select语句中为多列使用一个变量?

差不多,这两个查询是:

@myVar = 1 
SELECT * 
FROM TABLE 
WHERE someColumn = myVar 

VS:

@myQuery = ' 
SELECT * 
FROM TABLE 
WHERE someColumn = myVar' 

EXEC sp_executesql @myQuery, 
    N'@myVar INT, 
    @myVar 

我真正的查询是非常复杂得多。纵观统计数据,动态数据的读取次数大于10x。我想使这个查询是静态的来解决这个问题。它动态的原因在于,我的插入和选择是使用变量创建的。

我有类似:

@someVar1 = "column1, column2, column3" 
@someVar2 = "column4, column5, column6" 

,然后就可以

@myQuery = 'INSERT INTO '+ @someVar1 + 
      'SELECT ' + @someVar2 + ' FROM ....' 

有什么办法我只能这样做:

INSERT INTO @myVar1 
SELECT @myVar2 
FROM 
... 

我不知道ho否则要修复这个查询,并且它迫切需要修复。

编辑我做了一些修改。我忘记提到动态的东西也在插入语句中。这就是我醒来后发布帖子时会发生的情况。

+1

不,SQL Server不会让你用变量引用列,表等,你需要使用动态SQL。 –

+0

解决这个问题的真正方法是返回SELECT中的所有列,但改变应用程序层显示的内容而不是随时生成SELECT。 – JNK

+0

@JNK你能详细说明一下吗? – user1652427

回答

1

你正在追逐独角兽。 SQL Server不会让您在非动态查询中将@var替换为column1, column2。语法只是不支持你希望它做的事情(不是说它会改善情况)。

所以你需要以其他方式解决这个“问题”。我发现很难相信相同查询的动态版本导致读取中的10倍位移。如果是这种情况(并且你不只是夸大效果 - 请显示证据),这几乎肯定是由于参数嗅探,其中缓存的(静态)查询使用了导致一个计划形状的参数,而该计划形状对于具有不同查询文本或不同参数或两者的其他(动态)查询而言不是最佳的。您可以在运行时强制RECOMPILE并在一定程度上抵消这种情况,并确保查询文本每次都是相同的(这包括空格,大小写等)。

SET @myQuery = N'INSERT dbo.DestinationTable(' 
    + @DestinationColumns + ') 
    SELECT ' + @SourceColumns + ' 
    FROM dbo.SourceTable 
    WHERE someColumn = @myVar OPTION (RECOMPILE);'; 

但我不相信那是你的问题。我认为这可能比实际观察更多的感知/恐惧。

正如我在评论中提到的那样,如果您正在构建大量不同的动态SQL语句,则应考虑启用optimize for ad hoc workloads设置,这将防止计划缓存因您计划无法使用而臃肿再次。

SQL Sentry Plan Explorer的免费版本可以让你在半秒内很容易地完成你的计划,甚至让你上传他们,我们可以看到他们。这不会让我们剖析实际的查询文本,但它会显示查询本身的计划有所不同 - 查询是否动态构建并不重要,只是它不同而已。 声明:我为SQL Sentry工作。

+0

不为过。看~4440000读和vs〜350000。我已经尝试了重新编译和针对临时工作负载进行优化。不幸的是,我没有看到任何性能改进。 – user1652427

+0

@ user1652427请显示实际执行计划。我保证你有更多的不同,只是“一个是动态的,一个是静态的。” –

+0

查询计划完全不同。除了sp_executesql之外,没有什么区别,但我保证(我已经有几个其他的眼睛来确保我没有疯狂) – user1652427

相关问题