使用JDBC从Oracle检索150000条记录的最佳方法

使用JDBC从Oracle检索150000条记录的最佳方法,oracle,jdbc,Oracle,Jdbc,我今天一直在寻找这个问题的答案,似乎最好的方法在某种程度上会产生分歧 我有150000条记录需要使用JDBC从Oracle数据库中检索。使用一个select查询检索数据,并允许JDBC驱动程序使用Oracle游标和默认fetchSize从数据库传输记录,或者使用LIMIT/OFFSET将查询拆分为批,这样做更好吗 使用LIMIT/OFFSET选项,我认为优点在于您可以控制在每个块中返回的结果数量。缺点是查询执行多次,您还需要使用同一查询预先运行COUNT(*)以计算所需的迭代次数 一次检索所有数

我今天一直在寻找这个问题的答案,似乎最好的方法在某种程度上会产生分歧

我有150000条记录需要使用JDBC从Oracle数据库中检索。使用一个
select
查询检索数据,并允许JDBC驱动程序使用Oracle游标和默认
fetchSize
从数据库传输记录,或者使用
LIMIT/OFFSET
将查询拆分为批,这样做更好吗

使用
LIMIT/OFFSET
选项,我认为优点在于您可以控制在每个块中返回的结果数量。缺点是查询执行多次,您还需要使用同一查询预先运行
COUNT(*)
以计算所需的迭代次数

一次检索所有数据的优点在于,您依赖JDBC驱动程序来管理从数据库检索数据。缺点是,
setFetchSize()
提示有时会被忽略,这意味着我们最终可能会得到一个巨大的
resultSet
,一次包含所有150000条记录


如果能听到一些解决类似问题的实际经验,我将不胜感激。

我的偏好是保持安全的执行时间,并在中断时能够继续执行。我更喜欢这种方法,因为它是经得起未来考验的,并且尊重内存和执行时间限制。记住,你不是在为今天做计划,你是在为接下来的6米做计划。今天的15万可能在6个月内达到150万

我使用一个长度+1的配方来知道是否还有更多要获取的内容,尽管计数查询将使您能够在%中执行进度条,如果这很重要的话

当考虑150000个记录结果集时,这是一个内存压力问题。这将取决于每行的平均大小。如果它是一个包含三个整数的行,那么它很小。如果它是一行,包含一组文本元素来存储用户配置文件的详细信息,那么这可能非常大。所以要谨慎对待你所从事的领域


还需要询问-您可能不需要一直提取所有记录。应用同步模式可能很有用。仅提取更新日期比上次提取日期新的记录。

Oracle JDBC中的原生方法是使用
prepareStatement
进行查询,
executeQuery
和fetch 在循环中,使用定义的
fetchSize

是的,当然详细信息取决于Oracle数据库和JDBC驱动程序的版本,在某些情况下还取决于所需的
fetchSize
可以忽略。但典型的问题是,所需的fetch大小被重置为
fetchSize=1
,并且有效地为每条记录进行了一次往返。(并不是说你一次就能得到所有的记录)

您选择的
限制
在第一个视图中似乎很有意义。但是如果您调查了实现,您可能会决定不使用它

假设将结果集划分为15个块,每个块10K:

您打开15个查询,每个查询平均占原始查询资源消耗的一半(
OFFSET
选择数据并跳过它们)。 因此,您唯一能想到的是,处理大约需要7,5倍的时间

最佳实践

接受您的查询,编写一个带有JDBC fetch的简单脚本,使用10046 trace查看有效使用的fetch大小。
使用一系列取数大小进行测试,并观察性能;选择最佳记录。

记录将是varchar字段和数字主键。平均每个记录大约500字节。每次运行时都会处理所有记录似乎是合理的-是150000的静态限制,还是会随着时间的推移而增长?可能很容易增长,因为这是产品数据这是一次性操作吗?150k记录,每条记录有500字节,实际上在现代硬件中并不多见,因为在现代硬件中,通常有GB的可用内存。它应该只与一个简单的选择一起工作。使用
LIMIT
将使查询更加复杂,因为您需要对结果进行分页,并且DB需要对每个查询的数据进行排序。此操作每天会发生一次或多次。换句话说,如果打算读取所有行,则使用
OFFSET
进行分页是不合适的。另见