0

我有一段动态的 SQL。运行大约需要 4 分钟。如果我改为将其设为静态 SQL,则大约需要 20 秒。

几乎,这两个查询是:

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

与:

@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
...

我不知道如何修复这个查询,它迫切需要修复。

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

4

1 回答 1

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 工作。

于 2013-03-28T14:33:59.643 回答