我一直在研究Coldfusion/MS SQL多年,这是我见过的最奇怪的问题之一。问题本身已经得到解决,但我并不真正了解发生了什么;这个问题试图弄清楚可能的原因。慢速查询,CF 9&MSSQL 2008;腐败的执行计划?
的问题
在稳定的生产环境中,没有明显的原因,一个查询开始返回围绕1,000-1,500 MS(比平时慢约10倍)。我可以把它隔离到这一点:
<cfquery datasource="#ds#" name="query">
select 1
from eLearning.v_courseCompletion cc
where
cc.memberIncId = <cfqueryparam value="3" cfsqltype="cf_sql_integer"> and
cc.courseId = <cfqueryparam value="25" cfsqltype="cf_sql_integer"> and
cc.currentCourseCompleted = 1
</cfquery>
有什么奇怪的是,这种行为是在一个循环中时加重,即使有一个迭代,就像这个例子:
<cfloop from="1" to="1" index="i">
<cfquery datasource="#ds#" name="query">
select 1
from eLearning.v_courseCompletion cc
where
cc.memberIncId = <cfqueryparam value="3" cfsqltype="cf_sql_integer"> and
cc.courseId = <cfqueryparam value="25" cfsqltype="cf_sql_integer"> and
cc.currentCourseCompleted = 1
</cfquery>
</cfloop>
这应该和上面完全一样吧?该循环应该没有效果,但相反,该测试运行速度慢大约10倍,在7,000-16,000毫秒之间返回。这是如何检测到问题的;查询(埋在一个对象方法中)正在从循环体中调用,如果循环迭代超过5或6次请求超时。
对我来说,这表明了Coldfusion方面的一个问题,但重新启动服务,或者实际上机器什么都没做。
同时,一旦被隔离,我发现对查询本身进行任何更改都会导致性能恢复到预期水平,大约在150-190毫秒之间。例如:
- 改变所选择的字段(即
select *
) - 卸下表别名(
cc
) - 具有内嵌值
- 卸下任何条件更换或者
<cfqueryparam>
这些更改中的任何一个都“固定”了这个问题,但是在运行原始查询时,性能问题会返回。
解决方案
在这一点上我猜查询的执行计划已经损坏或什么的,做some Googling,跑DBCC FREEPROCCACHE
对DB服务器。这立即修复了问题。太好了,问题就解决了....
问题
从那以后,虽然,我已经做了一点研究和共识似乎是,执行计划“没有遭到损坏”。有some talksimilar problems与存储过程和parameter sniffing发生,但我没有在这里使用任何sp。我们选择一个相当复杂的视图,但是(eLearning.v_courseCompletion
)嵌套连接。这是问题吗?
基本上,这里究竟发生了什么?如何阻止它再次发生?
..和地狱是连接循环在CF?!?
版本
- ColdFusion的9.0.2.282541(64位)
- 的SQL Server Express 10.50.4297(64位)
- 两台服务器都赢Server 2008 R2的数据中心(64位)
啊太棒了,这很有道理。了解为什么从一个循环内运行它(甚至一次迭代)会如何影响性能?谢谢 – Molomby 2014-10-10 05:27:31
不,循环听起来不像罪魁祸首。我会责怪循环提供的其他一些情况,例如索引变量或使循环看起来像是责怪的东西。另外,你几乎总是可以避免在循环中运行cfquery。实际上这很有意义。 – 2014-10-10 12:23:38
谢谢你的跟进,但我向你保证,在循环中没有其他东西可以(应该)造成这种情况;上面提到的代码块是直接从我的测试用例中提取出来的(前后加上'getTickCount()')。循环的索引(或项目)变量根本不被查询引用,循环体中没有其他东西。据推测,在循环编译到Java期间,某些事情会发生故障?如果我能重现这个问题,我会深入一点。 – Molomby 2014-10-13 00:23:17