Sql server 慢速查询ColdFusion,SQL Server,依赖于空格

Sql server 慢速查询ColdFusion,SQL Server,依赖于空格,sql-server,performance,coldfusion,Sql Server,Performance,Coldfusion,我们遇到了一个问题,我们正在从ColdFusion 9调用SQL Server 2005。我不能发布原始查询,但它不是问题的焦点,我已经发布了导致问题的相关内容组合 我们有一个查询,它是下面示例查询的一个更复杂的版本,something列是主键。value参数没有更改。出于一些我们无法理解的奇怪原因,这个查询需要将近20秒的时间来运行 <cfquery result="q" datasource="dsn"> SELECT something FROM somewhere

我们遇到了一个问题,我们正在从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之间的DB驱动程序日志,没有任何异常。这里会发生什么


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

进一步的 其中一个执行计划似乎在其中一个子选择上查找不正确的索引,不清楚SQL Server为什么决定使用此替代执行计划,或者为什么其中一个索引出现错误

跟进
对于任何对可能导致糟糕执行计划的原因感兴趣的人来说,下面的问题被张贴在这里:

这可能是前几天突然发生的事情的症状(奇怪的巧合)

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

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

如果可能的话,通过SQL Server缓存来测试这一点,然后使用导致编译“坏”计划的值重新运行查询,您应该会看到类似的行为

这不是一个解决方案,但它将证明这可能是原因,并允许您解决不同值的计划中可能存在差异的根本原因


这个实验显然是基于知道在第一次调用查询时参数值是什么,这是。。。如果您确实了解它们,这对您来说是很幸运的。

从您的解释中不清楚执行时间是在SQL Server端还是在app Server端(或者这可能是您问题的一部分!)。您是否通过SQL事件探查器看到了这种情况?通过Profiler,这两个查询之间是否存在差异?如果第一次运行两次,第二次运行时是否仍然很慢?如果不是,那么缓慢可能是由编译和开发执行计划造成的。似乎SQL Server正在缓存一个缓慢的执行计划,我将更新我的问题。好奇的是,尝试运行没有结果属性的缓慢查询。那么,您是否看过这篇指出varchar vs nvarchar以及它如何不使用索引的文章?(我假设你在你的“复杂”问题中有更多的问题,你没有向我们展示这篇文章可能会产生的影响)再次感谢亚当!这似乎正是我们所看到的。我们将尝试跟踪原始查询或复制它,以找出使用错误计划的原因。。。如果有什么有趣的结果,我会更新。