简体   繁体   English

Jaybird(Firebird JDBC)ResultSet FetchSize —分页持久查询

[英]Jaybird (Firebird JDBC) ResultSet FetchSize — Pagination long lasting queries

I am trying to find a way how to force jaybird to do "pagination" in ResultSet. 我正在尝试找到一种方法来强制Jaybird在ResultSet中执行“分页”。 Suppose we have some long lasting sql query (it returns for example 5000 rows in 15 seconds). 假设我们有一些持久的sql查询(例如在15秒内返回5000行)。 However, fetching of first 50 (random) rows takes just a fraction of second. 但是,获取前50个(随机)行只需要几分之一秒。 So long as we do not add order by clause to the query, the server quickly returns first rows, which can be immediately shown in the client application. 只要我们不向查询添加order by子句,服务器就会快速返回第一行,这些行可以立即显示在客户端应用程序中。 This is btw the default behaviour of flamerobin client. 这是Flamerobin客户端的默认行为。

I try to simulate this behaviour with setting the Statement parameters like in the code below, but without success. 我尝试通过像下面的代码中那样设置Statement参数来模拟这种行为,但是没有成功。 Is there a way to force jaybird not to load all rows to the ResultSet? 有没有一种方法可以强制Jaybird不将所有行加载到ResultSet中? I suppose that the method stmt.setFetchSize(50) has this purpose but it is perhaps wrong. 我认为方法stmt.setFetchSize(50)具有此目的,但这可能是错误的。 Jaybird version used was 2.2.7 and Firebird version used was 2.5.4. 使用的Jaybird版本是2.2.7,使用的Firebird版本是2.5.4。 Thank you for your advices. 感谢您的建议。

String user = "user";
String pass = "pass";
Connection conn = DriverManager.getConnection(s, user, pass);
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(50);
stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
ResultSet rs = null;
String sql = "select * from TABLE"; //long lasting select 
boolean ok = stmt.execute(sql);
if (ok) {
    rs = stmt.getResultSet();
    while (rs.next()) {
         //do something
    }
}
if (rs != null) {
    rs.close();
}

if (stmt != null) {
    stmt.close();
}

I try to achieve same think as flamerobin client does -- on the fly load of the data to the table (only when we need them -- scroll down in the table). 我试图实现与Flamerobin客户端相同的想法-在将数据快速加载到表中时(仅在需要它们时-在表中向下滚动)。 We develop application which is a client of two tier ERP system (DB server firebird, client on netbeans platform).We wrote some database components which fills JXTable with data on the same principle like "interbase Delphi components" did in the past. 我们开发的应用程序是两层ERP系统的客户端(DB服务器firebird,netbeans平台上的客户端)。我们编写了一些数据库组件,该组件以与过去“ interbase Delphi组件”相同的原理填充数据。 The code above is symplified, in the component code we load the first 100 rows to the JTable table model and when user scrolls down we load another 100 rows etc. However I notice that the load time of the first 100 rows is the same as if we load all rows to the dataset. 上面的代码是简单的,在组件代码中,我们将前100行加载到JTable表模型中,当用户向下滚动时,我们加载另外100行等。但是,我注意到前100行的加载时间与我们将所有行加载到数据集中。 That is the code 那是代码

boolean ok = stmt.execute(sql);
if (ok) {
    rs = stmt.getResultSet();
    int rows = 0;
    while (rs.next() rows < 100) {
         //do something
         rows++;
    }
}

took practicaly same time as the first chunk of source code. 与第一批源代码几乎花了相同的时间。 It seems, that the stmt.execute(sql) command waits until all select rows are returned from server. 似乎stmt.execute(sql)命令等待,直到从服务器返回所有选择的行。 However I set that I want to get 50 rows chunks, so I supposed that the while cycle will start immediately after getting first 50 rows from the DB server. 但是,我设置为要获取50行数据块,因此我认为while周期将在从数据库服务器获取前50行数据后立即开始。 So I want start the while cycle after fetching first 50 rows (as if I set stmt.setMaxRows(50)), but I want to have oportunity to let the result set open and fetch another rows on demand. 所以我想在获取前50行后开始while周期(就像我设置了stmt.setMaxRows(50)一样),但是我想有机会让结果集打开并按需获取另一行。

Using setFetchSize normally does exactly what you expect: it will fetch rows in batches of the specified size (Firebird 3 can decide to return less when it considers the batch too big). 通常,使用setFetchSize完全可以达到您的期望:它将按指定大小批量提取行(Firebird 3在认为批量太大时可以决定减少返回的行数)。

However as you have specified defaultHoldable in your connection string, the result set is HOLD_CURSORS_OVER_COMMIT , and holdable result sets are fully cached client-side before they are returned. 但是,由于您在连接字符串中指定了defaultHoldable ,结果集为HOLD_CURSORS_OVER_COMMIT ,并且可保留的结果集在返回之前已在客户端完全缓存。

You either need to set the holdability to CLOSE_CURSORS_AT_COMMIT for this specific statement, or - if you do this for all statements - just remove the defaultHoldable from your connection string. 您需要为此特定语句将可保存性设置为CLOSE_CURSORS_AT_COMMIT ,或者-如果对所有语句都这样做-只需从连接字符串中删除defaultHoldable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM