我有一个动态的SQL。运行大约需要4分钟。如果我改为使其成为静态SQL,则需要大约20秒。
相当多,这两个查询是:
@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
...
我不知道如何修复此查询,并且迫切需要修复。
编辑我做了一些更改。我忘了提到动态的东西也在插入语句中。这就是我刚刚醒来后发帖的情况。
答案 0 :(得分:1)
你在追逐独角兽。 SQL Server不允许您在非动态查询中将@var
替换为column1, column2
。语法只是不支持您希望它做什么(不是它会改善情况)。
所以你需要以其他方式解决这个“问题”。我发现很难相信同一查询的动态版本会导致读取中的10倍位移。如果是这种情况(并且您不仅仅夸大效果 - 请显示证据),几乎可以肯定是由于参数嗅探,其中缓存的(静态)查询使用了导致一个计划形状的参数,并且该计划对于具有不同查询文本或不同参数或两者的其他(动态)查询,shape不是最佳的。您可以通过在运行时强制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工作。