在 HSQLDB 中选择 100+ 百万行

Posted

技术标签:

【中文标题】在 HSQLDB 中选择 100+ 百万行【英文标题】:Select 100+ millions of rows in HSQLDB 【发布时间】:2017-10-31 09:42:05 【问题描述】:

我必须在 HSQLDB 数据库上使用 JDBC 遍历包含 100+ 百万条记录的表,但我无法在合理的时间内完成。我用的是 hsqldb v2.4.0。

我尝试使用带有以下查询的PreparedStatement 对数据进行切片:

String select = "SELECT ID, NAME, VALUE FROM MY_TABLE ORDER BY ID OFFSET ? ROWS FETCH ? ROWS ONLY";

问题在于,我们遍历表格需要越来越多的时间。请注意,ID 列已编入索引。

我尝试设置提取大小,但它也不起作用:

String select = "SELECT ID, NAME, VALUE FROM MY_TABLE";
PreparedStatement selectStatement = connection.prepareStatement(select, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
selectStatement.setFetchSize(5000);

然后我遍历ResultSet

ResultSet result = selectStatement.executeQuery();
while (result.next()) 
    Long id = result.getLong(1);
    // do stuff ...
 

HSQLDB 仍然尝试获取表的所有行并且返回的ResultSet不适合内存。这是堆栈跟踪:

java.lang.OutOfMemoryError: Java heap space
at org.hsqldb.navigator.RowSetNavigatorData.ensureCapacity(Unknown Source)
at org.hsqldb.navigator.RowSetNavigatorData.add(Unknown Source)
at org.hsqldb.QuerySpecification.buildResult(Unknown Source)
at org.hsqldb.QuerySpecification.getSingleResult(Unknown Source)
at org.hsqldb.QuerySpecification.getResult(Unknown Source)
at org.hsqldb.StatementQuery.getResult(Unknown Source)
at org.hsqldb.StatementDMQL.execute(Unknown Source)
at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.executeQuery(Unknown Source)
at com.jolbox.bonecp.PreparedStatementHandle.executeQuery(PreparedStatementHandle.java:174)
at myclass at the line ResultSet result = selectStatement.executeQuery();

有没有办法在 HSQLDB 中实现这一点?

【问题讨论】:

如何循环访问ResultSet 我使用常规的 while 循环:while (result.next()) ... 你的 HSQLDB 版本是多少? 我想知道你循环的内容。您如何处理每条记录。 我使用的是 hsqldb v2.4.0(最新版本)。 【参考方案1】:

此问题与内存使用无关,因为此类 SELECT 使用的内存不多。

预计选择结果的时间会增加。 SELECT 中的 OFFSET 子句指示跳过了多少行。随着它变大,会选择和跳过更多行。

您需要将 SELECT 修改为:

SELECT ID, NAME, VALUE FROM MY_TABLE WHERE ID > ? ORDER BY ID FETCH ? ROWS ONLY

然后您像这样处理结果,使用带有 PreparedStatement 的正在运行的 lastID。

long lastID = -1;

// repeat the rest of the code until the result is empty
selectStatement.setLong(1, lastID);
selectStatement.setInt(2, 100000);

ResultSet result = selectStatement.executeQuery();
while (result.next()) 
 Long id = result.getLong(1);
 lastID = id;
 // do stuff ...

还有

【讨论】:

感谢您的回答,程序正在运行并且运行速度很快(4 分钟内处理了 1000 万行)。

以上是关于在 HSQLDB 中选择 100+ 百万行的主要内容,如果未能解决你的问题,请参考以下文章

数据库中的数百万行,只需要这么多

选择数据库以每天插入数百万行来为每个用户绘制图表

MySQL:具有 100+ 百万行的索引表

ssas 多维数据集中的百万行维度

如何在 SQL Server 中更新具有数百万行的大表?

MYSQL 从具有 100 万行的表中选择 distinct(indexed_column)