【问题标题】:Does jdbc dataset store all rows in jvm memoryjdbc 数据集是否将所有行存储在 jvm 内存中
【发布时间】:2015-06-15 10:33:40
【问题描述】:

我正在使用 java jdbc 应用程序从 DB 中获取大约 500,000 条记录。正在使用的数据库是 Oracle。获取每一行后,我将数据写入文件。由于完成获取整个数据大约需要一个小时,因此我正在尝试增加结果集的获取大小。我在多个链接中看到,在增加获取大小的同时,应该注意内存消耗。增加 fetch 大小实际上会增加 jvm 使用的堆内存吗?
假设提取大小为 10,并且程序查询总共返回 100 行。在第一次提取期间,结果集包含 10 条记录。一旦我读取了前 10 条记录,结果集就会获取下 10 条记录。这是否意味着在第二次获取后数据集将包含 20 条记录?较早的 10 条记录是否仍保留在内存中,还是在获取新批次时被删除? 任何帮助表示赞赏。

【问题讨论】:

  • Oracle 驱动程序只会在内存中保存由 fetchSize 定义的行数。因此,当第二次提取完成时,第一次提取的行将被释放并收集垃圾。但是 500.000 行的一个小时似乎非常慢。您确定您受到获取的限制,而不是语句本身吗?如果在 SQL*Plus 中使用set autotrace traceonly,语句会运行一个小时吗?您应该测量executeQuery() 和第一个ResultSet.next() 调用之间的时间 - 我猜,您正在等待 Oracle 准备查询结果
  • 是的,一个小时包括所有查询结果的提取。我希望增加提取大小可以减少整体提取时间。
  • 我执行的结果语句从互联网上的外部数据库中获取数据,然后我开始从结果集中写入我的本地文件,它开始写入,但是每当互联网断开连接时,写入就会中断。是不是因为结果集动态获取数据并写入文件?

标签: java oracle performance jdbc


【解决方案1】:

这取决于。不同的驱动程序可能表现不同,不同的ResultSet settings 可能表现不同。

如果您有CONCUR_READ_ONLYFETCH_FORWARDTYPE_FORWARD_ONLYResultSet,驱动程序几乎肯定会主动在内存中存储与您的获取大小相对应的行数(当然,之前行的数据将保留在内存中一段时间​​,直到它被垃圾收集)。另一方面,如果您有TYPE_SCROLL_INSENSITIVE ResultSet,驱动程序很可能会将所有获取的数据存储在内存中,以便您可以在数据中前后滚动。这不是实现此行为的唯一可能方式,因此不同的驱动程序(以及不同版本的驱动程序)可能具有不同的行为,但它是最简单的,也是我遇到的大多数驱动程序的行为方式。

【讨论】:

    【解决方案2】:

    虽然增加 fetch 大小可能对性能有所帮助,但我也会考虑调整 SDU 大小,它控制 sqlnet 层的数据包大小。增加 SDU 大小可以加快数据传输速度。

    当然,获取这 500,000 行所需的时间很大程度上取决于您要获取的数据量。如果需要一个小时,我猜您正在获取大量数据和/或您正在通过 WAN 从远程客户端进行操作。

    更改 SDU 大小:

    首先将服务器上的默认 SDU 大小更改为 32k(从 11.2.0.3 开始,您甚至可以使用 64kB 和从 12c 开始最多 2MB),方法是在服务器上的 sqlnet.ora 中更改或添加此行: DEFAULT_SDU_SIZE=32767

    然后修改你的 JDBC URL: jdbc:oracle:thin:@(DESCRIPTION=(SDU=32767)(HOST=...)(PORT=...))(CONNECT_DATA=

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      相关资源
      最近更新 更多