Select HSQLDB 中有 100+ 百万行
Select 100+ millions of rows in HSQLDB
我必须在 HSQLDB 数据库上使用 JDBC 遍历 table 超过 100 多条记录,但我无法在合理的时间内完成。我使用的是 hsqldb v2.4.0.
我尝试使用带有以下查询的 PreparedStatement
对数据进行切片:
String select = "SELECT ID, NAME, VALUE FROM MY_TABLE ORDER BY ID OFFSET ? ROWS FETCH ? ROWS ONLY";
问题是我们通过 table 需要越来越多的时间。请注意,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 仍然尝试获取 table 的所有行,并且返回的 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 中实现这个?
此问题与内存使用无关,因为此类SELECT没有使用太多内存。
select 预期结果的时间增加。 SELECT 中的 OFFSET 子句表示跳过了多少行。随着它变大,更多的行被 selected 和跳过。
您需要将 SELECT 修改为:
SELECT ID, NAME, VALUE FROM MY_TABLE WHERE ID > ? ORDER BY ID FETCH ? ROWS ONLY
然后你像这样处理结果,使用 运行 lastID 和 PreparedStatement。
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 ...
}
和
我必须在 HSQLDB 数据库上使用 JDBC 遍历 table 超过 100 多条记录,但我无法在合理的时间内完成。我使用的是 hsqldb v2.4.0.
我尝试使用带有以下查询的 PreparedStatement
对数据进行切片:
String select = "SELECT ID, NAME, VALUE FROM MY_TABLE ORDER BY ID OFFSET ? ROWS FETCH ? ROWS ONLY";
问题是我们通过 table 需要越来越多的时间。请注意,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 仍然尝试获取 table 的所有行,并且返回的 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 中实现这个?
此问题与内存使用无关,因为此类SELECT没有使用太多内存。
select 预期结果的时间增加。 SELECT 中的 OFFSET 子句表示跳过了多少行。随着它变大,更多的行被 selected 和跳过。
您需要将 SELECT 修改为:
SELECT ID, NAME, VALUE FROM MY_TABLE WHERE ID > ? ORDER BY ID FETCH ? ROWS ONLY
然后你像这样处理结果,使用 运行 lastID 和 PreparedStatement。
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 ...
}
和