Coldfusion 10中可重现的CFQUERYPARAM性能问题

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)

Rob*_*sen 2

答案 - 正如 @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)