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

时间:2015-08-12 10:25:09

标签: 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#" />

1 个答案:

答案 0 :(得分:2)

答案 - 正如@Raspin在评论中所确认,设置NOCOUNT ON可解决问题。

原始建议:

这可能是一个线索。你没有处理INDEX,但我的想法是SQL必须进行数据转换。我不认为这几行很重要,但我也不认为你会遇到这个问题:

Slow query with cfqueryparam searching on indexed column containing hashes

  

如果cfqueryparam将varchars作为unicode发送,则ColdFusion管理员中有一个设置可能会发生什么。如果该设置与列设置不匹配(在您的情况下,如果启用了该设置),则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>