6

我们有一个问题,我们从 ColdFusion 9 调用 SQL Server 2005。我无法发布原始查询,但这不是问题的焦点,我已经发布了导致问题的相关组合。

我们有一个查询,它是以下示例查询的更复杂版本,其中something列是主键。value 参数没有改变。由于某些我们无法理解的奇怪原因,此查询需要将近 20 秒才能运行....

<cfquery result="q" datasource="dsn">
  SELECT something
  FROM somewhere
  WHERE something = <cfqueryparam cfsqltype="cf_sql_integer" value="#value#"/> 
</cfquery>

请注意,如果您突出显示上面源代码的最后一行,cfqueryparam 标记后有一个空格。

以下查询完全不同,我相信您可以自己看到,运行需要 15 毫秒。

<cfquery result="q" datasource="dsn">
  SELECT something
  FROM somewhere
  WHERE something = <cfqueryparam cfsqltype="cf_sql_integer" value="#value#"/>
</cfquery>

cfqueryparam 后面没有空格。但是,在末尾添加两个空格也会产生 15 毫秒。如果我们最后回到一个空格,我们会在大约 20 秒内再次得到结果。

我们检查了 Java 和 SQL Server 之间的数据库驱动程序日志,似乎没有什么异常。这里会发生什么?


编辑

我们在 SQL Server 上运行了分析,它表明对于具有单个空格的查询,它使用的缓存执行计划与具有零个或多个空格的缓存执行计划不同。SQL Server 缓存查询的执行计划。它还使用完整的文字查询作为标识符。因此,当我们发送其他查询时,正在使用不同的执行计划。

更远

其中一个执行计划看起来像是在其中一个子选择上查找不正确的索引,目前尚不清楚 SQL Server 为何决定采用此替代执行计划,或者为什么其中一个索引看起来是错误的。

跟进

对于任何对可能导致错误执行计划的原因感兴趣的人,此处发布了后续问题:SQL Server 2005 cached an execution plan that could never work

4

1 回答 1

4

这可能是前几天在Railo 论坛上出现的问题的症状(奇怪的巧合)。

首次运行慢速查询版本时使用的参数值的性质有可能导致创建执行计划,该执行计划对该特定值“方便”,但对于更典型的后续值,该计划小于理想的。相反,当第一次运行第二个查询时,作为参数传递的值更典型地反映了查询的调用方式,因此执行计划更适合大多数其他值。

我个人还没有看到这种情况发生,但我已经阅读了足够多的时间。听起来确实像你所看到的。

如果可能,清楚地通过 SQL Server 缓存对其进行测试,然后使用导致编译“错误”计划的值重新运行查询,您应该会看到类似的行为。

这不是一个解决方案,但它会证明它可能是原因,并允许您解决不同值的计划差异的潜在原因。

这个实验显然是基于知道第一次调用查询时参数值是什么,这就是......如果你知道它们,那对你来说是幸运

于 2013-01-09T23:11:32.457 回答