ColdFusion的cfquery默默地失败了

时间:2012-11-09 12:54:23

标签: caching coldfusion coldfusion-9

我有一个检索大量数据的查询。

<cfsetting requesttimeout="9999999" >

<cfquery name="randomething" datasource="ds" timeout="9999999" >
    SELECT
        col1,
        col2
    FROM
        table
</cfquery>

<cfdump var="#randomething.recordCount#" /> <!---should be about 5 million rows --->

我可以使用python的cx_Oracle成功检索数据,并在python列表上使用sys.getsizeof返回22621060,所以大约21兆字节。

ColdFusion不会在页面上返回错误,我在任何日志中都找不到任何内容。为什么cfdump没有显示行数?

其他信息

这样做的原因是因为我有大约8000个较小的查询要针对randomthing查询运行。换句话说,当我对数据库运行这8000个查询时,该过程需要数小时才能完成。我怀疑这是因为我与其他几个数据库用户竞争,数据库陷入困境。

8000个较小的查询在col2期间得到col1的计数。

SELECT 
    count(col1) as count
WHERE 
    col2 < 20121109 
AND 
    col2 > 20121108

根据Adam Cameron's suggestions

我也开始使用maxrows属性来查看是否可以通过这种方式识别任何信息。

  • 当maxrows设置为1300000时,一切正常
  • 当maxrows为1400000或更高时,我收到此错误 enter image description here
  • 当maxrows为2000000时,我会发现原来的问题

更新

所以这不是cfquery的限制。通过使用QueryNew然后循环它来添加数据,我可以毫不费力地超过200万大关。

我还使用this question中的信息创建了一个ThinClient数据源,我没有观察到行为的任何变化。

数据库端的消息是

来自客户端的SQL * Net消息

SQL *将更多数据传输到客户端

我刚刚发现,通过使用瘦客户端和blockfactor1="100",我可以检索更多行(appx.3000000)。

6 个答案:

答案 0 :(得分:2)

数据库末端是否记录了任何内容?

我想知道timeout是否没有得到尊重,并且当JDBC工作时,JDBC正在“挂起”数据库。这是一个疯狂的猜测。如果你设置一个非常低的超时怎么办 - 例如:5秒 - 在5秒后出错,或者是什么?

浏览器也可能超时。你在<cfquery>块之前和之后用<cflog>写了什么内容。查看查询是否最终完成。

我不得不想知道一旦你把它们带回CF,你打算用这些22M记录做什么。不管它是什么,它听起来像CF是错误的地方做任何事情:CF不是用于繁重的数据处理,而是用于制作网页。如果您需要处理22M记录,我怀疑您应该在数据库上执行此操作。也就是说,我猜测你正在做什么没有信息继续下去,所以我认为这可能是一个很好的理由去做。

答案 1 :(得分:1)

您是否尝试将cfquery包裹在cftry个标签中以查看是否有报告内容?

<cfsetting requesttimeout="600" >

<cftry>
    <cfquery name="randomething" datasource="ds" timeout="590" >
        SELECT
            col1,
            col2
        FROM
            table
    </cfquery>

    <cfdump var="#randomething.recordCount#" /> <!--- should be about 5 million rows --->

    <cfcatch type="any">
        <cfdump var="#cfcatch#">
    </cfcatch>
</cftry>

答案 2 :(得分:1)

这只是一个想法,但你可以试一试:

您提到使用QueryNew,您可以成功添加所需的超过200万条记录。

此外,当您的maxRows少于1,300,000件时,工作正常。

那么为什么不首先查询count(*)表中的记录总数,除以一百万并向上舍入,然后cfloop超过该数字执行{{1}的查询每次迭代都有{和maxRows=1000000 ...

startRow=((i - 1 * 1000000) + 1)从循环内到数组的每个查询然后在完成所有操作时,循环遍历数组,将记录推送到新的Query对象中。这样,您最终会得到一个包含您尝试检索的所有记录的查询。

可能会遇到内存问题,而表现不佳,但是嘿 - 这就是Coldfusion,那些是课程的标准,有时是疯狂的事情发生/工作。

(您可以随时将每个查询的结果附加到您从ArrayAppend构建的那个查询的结果,而不是将每个查询推送到数组上,但它会更容易调试并查看如何如果你按照自己的方式构建一个数组,它就会失效。)

(另外,使用CF可以处理的大小内的多个查询,然后您可以通过循环遍历数组然后执行每个查询而不是构建一个大规模查询来执行您需要的过程 - 将节省处理时间和内存,但取决于您是否需要在单个Query对象中设置完整结果)

答案 3 :(得分:1)

如果您的日期范围是一致的,我会在sql中建议一些聚合函数,而不是使用cf处理它。类似的东西:

select col1, count(col1), year(col2), month(col2)
from table
group by year(col2), month(col2)
order by year(col2), month(col2)

如果您还需要详细级别,请添加day()。你可以通过日期部分获得真正的创意。

这应该会大大加快整个运行时间,减少主查询的大小。

答案 4 :(得分:0)

你的问题是ColdFusion无法超时SQL。自从我相信CF6以来,这一直是一个问题。所以基本上发生的事情是cfquery花费的时间超过了9999999秒,但CF不能超时JDBC,所以它等到后来尝试运行cfdump(内部使用cfoutput)并且这被报告为超时因为请求现在被认为有跑得太久了。

正如亚当所指出的那样,无论你想要做什么都太大了,CF无法真实地处理,要么需要将其切割成较小的工作,要么完全在数据库中处理。

答案 5 :(得分:0)

因为事实证明服务器内存不足,显然cfquery占用的内存比python list多得多。

CFMonitor Chart

Barry's comment让我朝着正确的方向前进,除了存在之外,我对服务器监控器的了解还不多。

事实证明I am also not very good at reading,在application.log文件中记录的错误是

超出GC开销限制包含或处理的特定文件序列为:\ path \ to \ index.cfm,line:10“

Java堆空间包含或处理的特定文件序列是:\ path \ to \ index.cfm

我最终将使用Adams suggestion并让数据库进行处理。至少现在我能够解释为什么事情变慢而不只是说“我不知道”。