Ras*_*pin 7 sql-server coldfusion sql-server-2008-r2 coldfusion-10
我一直能够通过Coldfusion 10查询SQL Server 2008 R2来重现严重的参数化性能问题,并且有兴趣知道其他人得到了什么.代码如下.
测试做了什么? 它创建一个包含100行的表.除一个数据列外,数据列均为空白.然后它运行Coldfusion查询10次,一半使用cfqueryparam,一半使用简单的字符串.它返回一个列表,其中包含每个响应时间.当我运行它时,除了初始调用之外,参数化查询的运行速度要慢得多(大约10-100次).
SQL Server中发生了什么? 我可以看到SQL服务器没有区别.在这两种情况下,计划缓存指示几乎相同的计划(一个显然是参数化的),并且剖析器显示两者的快速响应.然而,Coldfusion与参数化查询斗争.
什么解决了这个问题? 奇怪的是,如果我将varchar更改为nvarchar,问题就会消失.或者如果我将非空白移动到开头,则两个响应都很慢(如图所示).如果我将所有记录留空或非空白,那么问题就不存在了.它必须是混合物.我不能在CF9中重现这个问题,但还没有尝试过CF11.
<cfset datasource="yourdatasource" />
<cfquery name="createdata" datasource="#datasource#">
--EMPTY PREVIOUS TESTS
IF OBJECT_ID('aaatest', 'U') IS NOT NULL
BEGIN
TRUNCATE TABLE aaatest;
DROP TABLE aaatest;
END
--CREATE TABLE TO CONTAIN DATA
CREATE TABLE [dbo].[aaatest](
[id] [int] NOT NULL,
[somedata] [varchar](max) NULL,
[somekey] [int] NOT NULL
) ON [PRIMARY];
--INSERT 100 ROWS WITH 99 BLANK AND 1 NON-BLANK
WITH datatable AS (
SELECT 1 id
UNION all
SELECT id + 1
FROM datatable
WHERE id + 1 <= 100
)
INSERT INTO aaatest(id,somekey,somedata)
SELECT id,1,case when id=99 then 'A' else '' end
FROM datatable;
</cfquery>
<cfset results=[] />
<cfloop from="1" to="10" index="n">
<!--- use parameters for every other test --->
<cfset useParameters = (n mod 2 is 0) />
<cfquery name="myquery" datasource="#datasource#" result="result">
SELECT somedata
FROM aaatest
WHERE somekey=
<cfif useParameters>
<cfqueryparam value="1" CFSQLType="CF_SQL_INTEGER" />
<cfelse>
1
</cfif>
</cfquery>
<!--- store results with parameter test marked with a P --->
<cfset arrayAppend(results,(useParameters?'P':'')&result.executiontime) />
</cfloop>
<cfdump var="#results#" />
Run Code Online (Sandbox Code Playgroud)
答案 - 正如 @Raspin 在评论中所确认的,设置NOCOUNT ON修复了问题。
原来的建议:
这可能是一个线索。你不是在处理索引,但我的想法是 SQL 必须进行数据转换。我认为这么少的行并不重要,但我也不认为你会遇到这个问题:
使用 cfqueryparam 在包含哈希的索引列上搜索的慢速查询
可能发生的情况是 ColdFusion 管理员中有一个设置,说明 cfqueryparam 是否将 varchar 作为 unicode 发送。如果该设置与列设置不匹配(在您的情况下,如果启用该设置),则 MS SQL 将不会使用该索引。
我建议尝试的另一件事是将整个SELECT声明包含在IF声明中。我的想法是,也许 SQL 认为它无法重用查询计划。这意味着您的性能损失实际上是重新编译:
<cfloop from="1" to="10" index="n">
<cfset useParameters = (n mod 2 is 0) />
<cfif useParameters>
<cfquery name="myquery" datasource="#datasource#" result="result">
SELECT somedata
FROM aaatest
WHERE somekey= <cfqueryparam value="1" CFSQLType="CF_SQL_INTEGER" />
</cfquery>
<cfelse>
<cfquery name="myquery" datasource="#datasource#" result="result">
SELECT somedata
FROM aaatest
WHERE somekey= 1
</cfquery>
</cfif>
<cfset arrayAppend(results,(useParameters?'P':'')&result.executiontime) />
</cfloop>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
536 次 |
| 最近记录: |