【问题标题】:The request has exceeded the allowable time limit & Java Heap Space Null errors请求已超过允许的时间限制 & Java Heap Space Null 错误
【发布时间】:2016-10-10 20:52:12
【问题描述】:

我知道这个话题似乎被讨论过很多次,但是我尝试了所有提到的方法都没有成功。

我不断收到错误:

请求已超过允许的时间限制标签:CFQUERY
错误发生在第 152 行。

还有

Java堆空间为空
错误发生在-1行。

在同一个 html 页面上。

我相信 Java 堆空间错误会导致超时,反之亦然。

发生超时的程序是

        <CFQUERY DATASOURCE="#datasource#" USERNAME="#username#" PASSWORD="#password#" NAME="myQuery" CACHEDWITHIN="#CreateTimeSpan(0,0,5,0)#">
    SELECT tableA.productid, tableA.userid, tableA.salesid, tableA.productname, tableA.price, tableA.units, tableA.currency, tableA.terms, tableA.description, tableA.pic, tableA.minorder, tableA.salesid, tableB.id, tableB.company, tableB.city, tableB.state, tableB.country, tableB.contact, tableB.skype
    FROM tableA LEFT OUTER JOIN tableB
    ON tableA.userid = tableB.userid
        WHERE tableA.category = <cfqueryparam value = "#cat#" cfsqltype = "cf_sql_integer" maxLength = "2">
        ORDER by tableA.ranks DESC
        </CFQUERY>

我不知道如何进一步“优化”?它只检索了大约 28,000 条结果记录,不是 200 万条。我正在使用 MySQL 数据库。

我已将我的 MaxPermSize 从 256MB 增加到 512MB,但问题似乎仍然存在,尤其是当搜索引擎进入网站进行索引时。我在具有 6GB RAM 的服务器上运行 CF9。以下是我在 CF 中的一些设置:

  • 最小和最大 JVM 堆大小均设置为 512MB。
  • (秒)后的超时请求设置为 60
  • JVM 版本 1.7.0_67
  • JVM 参数:

    -server -Dsun.io.useCanonCaches=false -XX:-UseGCOverheadLimit -XX:MaxPermSize=512m -XX:+UseParallelGC -Xbatch -Dcoldfusion.rootDir={application.home}/../ -Dcoldfusion.libPath= {application.home}/../lib

欢迎提出任何建议。提前致谢。

附加信息:

  1. 有26类产品
  2. 每个类别有 20-50K 条记录,并且每天都在增加
  3. 人们可能会也可能不会在一天中的不同时间访问所有 26 个不同的类别
  4. 并非所有类别每天都会更新,但有些类别会更新

【问题讨论】:

  • 拥有这 28,000 条记录后,您将如何处理它们?
  • 要测试错误是否与从数据库查询中获取的行数有关,您可以在 MySQL SQL 语句的末尾,在 ORDER BY 子句之后添加一个 LIMIT 子句... ORDER BY tableA.ranks DESC LIMIT 1。这并不能“解决”问题,它只会帮助确定错误是否与查询返回的行数有关。 (我在 JVM 设置中没有看到 -Xms 和 -Xmx 参数,您表示它们都设置为 512m。)
  • 至于“优化” MySQL 查询,我会将实际的 SQL 文本带到另一个客户端,然后运行 ​​EXPLAIN EXTENDED,然后查看执行计划。我还想看看执行 SQL 查询需要多少时间。 (添加 SQL_NO_CACHE 提示以绕过 MySQL 缓存,如果已启用。)也许查询没有有效地使用可用索引和/或合适的索引不可用。 (我们没有看到从数据库返回行后代码在做什么。)
  • @Jack:在我看来你需要弄清楚错误是与返回的行数有关,还是与时间量有关 查询运行,或者如果它是别的东西。与其推测,我会按照我的建议去做。也就是说,将发送到 MySQL 服务器的实际 SQL 文本带到不同的客户端,看看执行需要多长时间。我还会做一些简单的测试,比如添加一个 LIMIT 子句,以测试“仅检索 1 条记录是否会导致 CF 服务器出现问题?”只是我的建议。 (SO 是一个问答网站,不是调试服务。)
  • 如果您获得 28,000 条记录并且只使用其中的 20 条,也许您可​​以考虑返回更少记录的方法。 tableA.ranks 上的过滤器可能是合适的。

标签: java mysql coldfusion jvm


【解决方案1】:

每个类别有 20-40k 产品,有 20 个类别且行大小未知,因此您需要对数据缓存做出一些真正的架构决策(如果您确实使用缓存)。目前,每个类别 id 参数将是该查询的唯一缓存,其生存时间为五分钟,消耗一定量的堆空间。此外,它必须在请求期间从缓存中复制出来,并且会消耗内存,直到可以收集为止。另请注意,permgen 与堆大小无关。

我建议不要通过仅询问该页面的记录来查看数据库服务器如何处理它的缓存。内置查询缓存是非常情境化的,这不是其中一种情况。 30k 条记录可能看起来并不多,直到您意识到您拥有产品描述和其他每个半兆的大文本块。如果可以的话,对于任何具有强大目录的典型商业网站,我强烈建议您至少使用一两个 gig。 (您说“我在具有 6GB RAM 的服务器上运行 CF9。”希望其中一些可以免费分配给 JVM)。在这种情况下,更多的内存只会将问题推迟到以后,如果有的话。

此外,将 permgen 拉回 256。512 permgen 相当高,即使对于大型企业应用程序也是如此。

当请求进入时,您的应用当前的运行方式如下所示。

  1. 查询标签命中并返回结果
    1. 缓存命中 - 结果从缓存中复制出来,浪费了一些兆字节
    2. 缓存未命中 - 结果从数据库中流入,占用了一些浪费的兆字节,并额外复制到缓存区域(但您避免了数据库加载时间和传输时间,我怀疑您的大部分时间都花在了转移而不是查询)
  2. 您只使用了一小部分查询
  3. 查询已被垃圾回收

在轻负载下,您的服务器可能几乎无法跟上。谁知道您的缓存区域能够避免流失的频率。

其他跟进:

听起来你做这一切只是为了分页的行数。实际上,您可以将总行数放入仅返回一页记录作为子查询的查询中。如果您想拆分为两个查询——一个用于行计数,一个用于该行的记录,那么前者是缓存的一个很好的竞争者。它是不会经常变化的数据,如果确实如此,那么你是否稍微落后也没关系。此外,它超级小,实际上缓存而不是一直询问数据库是有意义的。

【讨论】:

  • 我有 26 个类别,其中一些有 40K 条记录。那么 MaxPermSize 应该是 256m?什么被认为是企业应用程序?目前我每天大约有 20 万个请求。
  • Permgen 与 Java 类和其他 Java 实体的数量有关。它不是受请求计数影响的“活动”内存。堆用于此。你需要一大堆类来填满 512 兆,比如数百万行代码。
  • 当我在研究时,当出现“Java heap space null”错误时,为什么人们会说增加“MaxPermSize”?
  • @jack 我真的不知道,但我相信我会让你走上比试图增加 permgen 更正确的道路。
  • 通过仅询问该页面的记录来了解 DB 服务器如何处理它 同意。查看pagination
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 2010-09-07
  • 1970-01-01
相关资源
最近更新 更多