2011-12-18 37 views
4

在研究了一下工作之后,我注意到我正在使用的应用程序使用默认的抓取大小(对于我所知的Oracle,这是10)。问题是,在大多数情况下,用户获取大量数据(从几千到几十万),默认10是一个巨大的瓶颈。JDBC/Hibernate抓取大小和内存问题

因此,这里明显的结论是使提取大小更大。起初,我正在考虑将默认设置为100,并将其提升到1000以进行多个查询。但是后来我在网上看到,为了防止内存问题(即JVM堆不能处理这么多数据),默认值太小,我应该担心它吗?

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

回答

4

通过设置获取大小太大,你冒着冒险OutOfMemoryError

无论如何,你需要所有这些记录的事实可能是不合理的。更多机会您需要实体由返回的ResultSet s反映s ...将获取大小设置为10000意味着您正在堆积由JDBC类表示的10000条记录。当然,你不会通过你的应用程序传递这些信息。你首先将它们转换成你最喜欢的业务逻辑实体,然后把它们交给你的业务逻辑执行器。通过这种方式,只要JDBC获取下一个获取批量时,第一个获取批量的记录就可用于GC。

通常,这种转换在一段时间内完全是由于上述的内存威胁导致的。

有一件事你是绝对正确的,但:你应该测试定义明确要求调整前的表现。

+0

嗯所以基本上,当将读取大小从10跳到100时,我可以说100我只在堆上获得了90多个jdbc对象,并且在调用之后它们将被GCed(所以所有时间我将在堆中至多有100个jdbc对象) ? – 2011-12-18 16:46:16

+0

是的,属于迭代的'ResultSet'的100个jdbc对象。或者,至少,这将被认为是一个合理的实现......它不是由JDBC规范AFAIK强制的。 – yair 2011-12-18 17:26:14

1

因此,这里明显的结论将是使提取大小更大。

也许同样显而易见的结论应该是:“让我们看看,如果我们可以在用户带回对象的数量减少。”当Google返回结果时,它会按25或50批次进行排序,最大程度地被分类为您认为有用。如果您的用户正在回收数千个对象,那么您可能需要考虑如何减少这些对象。数据库可以做更多的工作吗?是否还有其他的操作可以写出来消除这些对象?对象本身是否更聪明?

+0

那么这是我的“第二号”,但在咨询了一些拥有更大“业务”知识的同事之后,结论很简单:我们需要将所有数据存储在内存中。所以很不幸,我没有看到减少数字的方法。 – 2011-12-18 16:42:03

+0

然后你需要更多的记忆 - 没有两种方式。如果您运行的是32位JVM,则会针对2GB JVM堆大小限制运行。除了64位和分配更大的堆之外,你无能为力。 – duffymo 2011-12-18 16:58:44

+0

是的,我知道:)我的整个问题更像是“我在内存中有XXXk对象,将提取大小从10到100/1000在这种情况下将是一个大问题”,但我想我只是需要请求一些体面的负载测试来看看会发生什么。 – 2011-12-18 18:22:42