【问题标题】:JDBC/Hibernate Fetch Size and memory issuesJDBC/Hibernate 获取大小和内存问题
【发布时间】:2012-01-23 02:03:28
【问题描述】:

在对工作进行了一些调查后,我注意到我正在处理的应用程序使用的是默认提取大小(据我所知,Oracle 为 10)。问题在于,在大多数情况下,用户会获取大量数据(从几千到几十万不等),而默认的 10 确实是一个巨大的瓶颈。

所以这里的明显结论是使获取大小更大。起初,我正在考虑将默认值设置为 100,并将其设置为 1000 以进行多个查询。但是后来我在网上读到,默认值很小以防止内存问题(即当 JVM 堆无法处理这么多数据时),我应该担心吗?

我还没有看到任何进一步的解释。这是否意味着在获取结果集时更大的获取大小意味着更多的开销?还是他们只是意味着默认情况下我可以获取 10 条记录,然后 GC 它们并获取另外 10 条等等(而假设一次获取 10000 条记录会导致 OutOfMemory 异常)?在这种情况下,我真的不在乎,因为无论如何我都需要内存中的所有记录。在前一种情况下(更大的结果集意味着更大的内存开销)我想我应该先对其进行负载测试。

【问题讨论】:

    标签: java hibernate memory jdbc out-of-memory


    【解决方案1】:

    通过也设置获取大小,您 冒着OutOfMemoryError 的风险。

    您无论如何都需要所有这些记录这一事实可能是不合理的。您需要返回的ResultSets 所反映的 entities 的机会更大... 将 fetch size 设置为 10000 意味着您将堆积 10000 条由 JDBC 类表示的记录。当然,您不会通过应用程序传递这些信息。您首先将它们转换为您最喜欢的业务逻辑实体,然后将它们交给您的业务逻辑执行器。这样,一旦 JDBC 获取下一个 fetch bulk 时,来自第一个 fetch bulk 的记录就可以用于 GC。

    通常,由于上述内存威胁,这种转换一次完成一小部分。

    但有一点你是绝对正确的:你应该在调整之前用明确定义的要求测试性能。

    【讨论】:

    • 嗯,所以基本上当将 fetch 大小从 10 增加到 100 时,我只能在堆上获得 90 个 jdbc 对象,并且它们将在调用后立即被 GC(所以我最多只能有堆中有 100 个 jdbc 对象)?
    • 是的,100 个 jdbc 对象属于迭代的ResultSet。或者,至少,这将被认为是一个合理的实现......它不是由 JDBC 规范 AFAIK 强制的。
    【解决方案2】:

    所以这里的明显结论是使获取大小更大。

    也许一个同样明显的结论应该是:“让我们看看我们是否可以减少用户带回的对象的数量。”当 Google 返回结果时,它会以 25 或 50 个为一组,按最有可能被您认为有用的方式排序。如果您的用户要带回数以千计的对象,也许您需要考虑如何减少它。数据库可以做更多的工作吗?是否可以编写其他操作来消除其中一些对象?物体本身会更智能吗?

    【讨论】:

    • 好吧,那是我的“第二名”,但在咨询了一些拥有更丰富“业务”知识的同事之后,结论很简单:我们需要将所有数据都保存在内存中。所以不幸的是,我看不到减少数字的方法。
    • 那么你需要更多的内存——没有两种方法。如果您运行的是 32 位 JVM,您将遇到 2GB JVM 堆大小限制。对此您无能为力,只能使用 64 位并分配更大的堆。
    • 是的,我知道 :) 我的整个问题更像是“我的内存中有 XXXk 个对象,在这种情况下将获取大小从 10 提高到 100/1000 将是一件大事",但我想我只需要请求一些体面的负载测试来看看会发生什么。
    猜你喜欢
    • 2016-12-26
    • 2010-10-15
    • 2020-02-18
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    相关资源
    最近更新 更多