加快QoQ或替代方法?

时间:2011-05-05 15:43:01

标签: coldfusion adobe railo

我正在构建一个执行具有多个连接的主查询的应用程序。然后,该查询数据可供整个应用程序在全局变量中使用。查询在每次刷新页面时刷新或获取最新结果集;所以它只是在请求的生命周期中处于相同的状态。

在本应用程序的其他部分,我有时会对此数据运行100个QoQ - 通常是递归函数调用的结果。然而,虽然QoQ是一个很棒的功能,但它并不是太快,有时在糟糕的一天,页面加载可能在3000 - 5000毫秒之间。它的速度还不够快。

我是否可以采用任何一种优化技术来使QoQ表现更快或者可能是另一种方法?我阅读了Ben Nadel关于Duplicate()函数的一篇有趣的文章 - 是否有使用它的范围,如果有,怎么做?

我很想听听你的想法。

不要担心疯狂的建议,这是个人项目所以我愿意承担风险。我正在使用与CF8兼容的Railo上运行它。

非常感谢, 迈克尔。

3 个答案:

答案 0 :(得分:2)

在没有看到QoQ的代码和复杂性的情况下,很难确定最佳方法,但是您可以做的一件事是使用结构来索引QoQ之外的记录。使用QoQ的大部分开销是构建新的查询对象,并且使用struct write only方法比例如循环原始查询并进行比较更有效。

例如:

<!--- build up index --->
<cfset structindex = {} />
<cfset fields = "first,last,company" />
<cfloop list="#fields#" index="field">
    <cfset key = "field:#field#,value:#q[field][currentrow]#" />
    <!--- initialize each key (instead of using stuctkeyexists) --->
    <cfloop query="q">
        <cfset structindex[key] = "" />
    </cfloop>
    <cfloop query="q">
        <!--- update each key with list of matching row indexes --->
        <cfset structindex[key] = listappend(structindex[key], currentrow) />
    </cfloop>
</cfloop>

<!--- save structindex to global variable --->

<!--- output rows matching index --->
<cfset key = "field:company,value:stackexchange" />
<cfoutput>
    <cfloop list="#structindex[key]#" index="row">
        #q.last[row]#, #q.first[row]# (#q.company[row]#)<br />
    </cfloop>
</cfoutput>

如果这与您的需求不匹配,请提供QoQ语句的一些示例以及主查询中有多少条记录。

答案 1 :(得分:1)

首先,我会查看主查询所花费的时间。如果它可以缓存一段时间并占用了大量的页面加载时间,我会缓存它。

接下来,我会看一下递归调用。如果它们可以迭代生成,那么可能会加快速度。我意识到这并不总是可行的。如果这不是你最大的时间下沉,我会感到惊讶。但是,如果不了解您正在做的事情,很难帮助您优化这一点。

我也可以考虑在DB服务器上编写一些递归QoQ的存储过程,这些存储过程旨在快速处理数据并有效地切片和切块。 CF不是 - QoQs非常有用,但不是速度恶魔(如你所知)。

最后,我会寻找直接过滤器,而不是使用QoQ。相反,我只是在标准cfoutput标记中对主查询运行循环,并在运行中进行过滤。这意味着您将循环遍历主查询一次,而不是主查询一次,结果查询一次。

答案 2 :(得分:1)

这里有两个主要的解决方案。首先,您可以使用QoQ之外的记录在CF中执行某些操作。我已经发布了我的建议。另一个是在db中做所有事情。我发现这样做的一种方法是使用子查询作为临时表。您甚至可以将sql语句保存在全局变量中,然后在与当前QoQ相同的位置引用它,但对数据库进行实际查询。它可能听起来比一次行程DB慢,然后很多QoQ,但实际上它可能不是有效索引。

select *
from (
    #sqlstring#
) as tmp
where company = 'stackexchange'

我实际上已经为具有复杂标准的系统执行了此操作,该标准既包括用户应该访问的记录,也包括他们可以在这些记录中过滤的内容。采用这种方法意味着您始终知道内部记录的来源,而不是试图确保每个查询都正确地提取。

编辑: 实际上,在可能的情况下使用queryparams更安全(并且通常更有效)。我发现这可以通过包含sql语句的文件来完成......

select *
from (
    <cfinclude template="master_subquery.cfm" />
) as tmp
where company = 'stackexchange'