5

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

<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 成功检索数据,并sys.getsizeof在 python 列表中使用返回 22621060,即大约 21 兆字节。

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

附加信息

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

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

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

根据亚当卡梅隆的 建议

我也开始玩弄这个maxrows属性,看看我是否能以这种方式辨别任何信息。

  • 当 maxrows 设置为 1300000 时一切正常
  • 当 maxrows 为 1400000 或更大时,我收到此错误 在此处输入图像描述
  • 当 maxrows 是 2000000 我观察到我原来的问题

更新

所以这不是 cfquery 的限制。通过使用QueryNewthen 循环它来添加数据,我可以毫无问题地超过 200 万大关。

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

数据库端的消息是

来自客户端的 SQL*Net 消息

SQL*Net 向客户端发送更多数据

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

4

6 回答 6

2

数据库结束时是否记录了任何内容?

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

浏览器也可能超时。<cfquery>什么说你在块之前和之后写一些东西到日志中,用<cflog>. 查看查询是否最终完成。

我想知道一旦你把这些 22M 记录带回 CF,你打算如何处理它们。不管它是什么,在我看来 CF 是做任何事情的错误场所:CF 不是用于繁重的数据处理,而是用于制作网页。如果您需要处理 22M 记录,我怀疑您应该在数据库上进行。也就是说,我在猜测你在做什么而没有继续的信息,所以我认为这样做可能是有充分理由的。

于 2012-11-09T13:10:24.603 回答
1

您是否尝试过包装您cfquerycftry标签以查看是否报告了任何内容?

<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>
于 2012-11-27T17:15:32.023 回答
1

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

您提到使用QueryNew您可以成功添加您需要的超过两百万条记录。

此外,当您maxRows的数量少于 1,300,000 时,事情会按预期工作。

那么为什么不首先count(*)对表中的记录总数进行查询,除以一百万并向上取整,然后cfloop在该数字上执行查询,maxRows=1000000startRow=((i - 1 * 1000000) + 1)在每次迭代时...

ArrayAppend每个查询从循环内到一个数组,然后当它全部完成后,循环遍历您的数组,将记录推送到一个新的 Query 对象中。这样,您最终会得到一个包含您尝试检索的所有记录的查询。

可能会遇到内存问题,并且它的性能不会那么好,但是嘿 - 这是 Coldfusion,这些都是课程的标准,有时会发生疯狂的事情/工作。

(您可以随时将每个查询的结果附加到您正在构建的那个,QueryNew而不是将每个查询推送到一个数组中,但是如果不这样做,它会更容易调试并查看您能走多远如果您随时构建一个数组,则可以工作。)

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

于 2012-11-29T14:03:43.763 回答
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()。您可以使用日期部分获得真正的创意。

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

于 2012-11-30T00:20:26.310 回答
0

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

CFMonitor 图表

正是Barry 的评论让我朝着正确的方向前进,在此之前我对服务器监视器知之甚少,除了它存在的事实。

事实证明,我也不是很擅长阅读,在 application.log 文件中记录的错误是

超出 GC 开销限制 包含或处理的文件的具体顺序是:\path\to\index.cfm,行:10"

Java堆空间包含或处理的文件的具体顺序是:\path\to\index.cfm

我最终会接受 Adams的建议,让数据库进行处理。至少现在我可以解释为什么事情进展缓慢,而不仅仅是说“我不知道”。

于 2012-12-01T22:08:40.953 回答
0

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

正如亚当指出的那样,无论您尝试做什么,对于 CF 来说都太大而无法实际处理,并且要么需要被分割成更小的工作,要么完全在数据库中处理。

于 2012-11-10T06:10:00.430 回答