2016-10-11 17 views
1

私は、何百万ものレコードを持つテーブルを持っています。システムを高速化するために、私はJavaコードでページ区切りの概念を実装する必要があります。私は一度に1000レコードを取り出して処理し、さらに1000レコードを選んで処理しなければなりません。私はすでにいくつかのことを試みており、どれも働いていません。クエリが、それは私に結果を与えるが、クエリがSELECT * from TABLENAME Where ROWNUM BETWEEN 10 and 20のあるとき、それは空の結果セットを返すSELECT * from TABLENAME Where ROWNUM BETWEEN 0 and 10あるとき、上記の例でJavaのページネーションJDBC

1) String query = "select * from TABLENAME" + " WHERE ROWNUM BETWEEN %d AND  %d"; 
sql = String.format(query, firstrow, firstrow + rowcount); 

- 私が試した事のいくつかを以下に示します。私もDBで実行しようとしましたが、空の結果セットが返されました(理由はわかりません)

2)preparedStatement.setFetchSize(100);私はJavaコードでこれを持っていますが、それでもテーブルからすべてのレコードを取り出します。このステートメントを追加しても、とにかく私のコードには影響しませんでした。

助けてください!

+0

なぜですか?単にResultSetをループしてデータベースのカーソルを処理させるのはなぜですか? –

+0

'setFetchSize'は、ドライバが次の_(fetchSize)_' resultSet.next() '呼び出しに対して一度に要求する行数だけを指定します。それはあなたにすべての行を依然として提供します。代わりに 'setMaxRows'を探しているかもしれません。 –

+0

100万以上のレコードをフェッチしようとすると "Out of Memory"になります。 – user3845894

答えて

4

実際に結果を改ページするのではなく、結果をバッチで処理する必要はありません。この場合、setFetchSizeを使用してフェッチサイズを1000に設定し、通常通り(resultset.next()を使用して)結果セットを反復処理し、反復処理の結果を処理します。 setFetchSizeとそれが何をするかについては、多くのリソースがあります。これを行う方法を記述した多くのリソースが存在する場合は、Oracleの改ページについて

:いくつかの研究を行います。ちょうどウェブ検索をしてください。ここでそれを行う方法を説明したリソースのカップルです:

あなたがすることはできませんので、あなたが一貫性のある順序(ORDER BY句)を定義していない場合はページネーションは非常に有用ではありません返される順序に依存します。 https://stackoverflow.com/a/10318244/908961

の答えから、あなたの結果を得るために選択したサブを行う必要があり12cのより古いOracleを使用する場合:
この答えはあなたのBETWEEN文が動作していない理由を説明します。ような何か:

SELECT c.* 
FROM (SELECT c.*, ROWNUM as rnum 
     FROM (SELECT * FROM TABLENAME ORDER BY id) c) c 
WHERE c.rnum BETWEEN %d AND %d 

は、Oracle 12C以上を使用している場合は、私は新しいOFFSETFETCH構文を使用して、代わりにrownumをいじることをお勧めします。http://docs.oracle.com/javadb/10.10.1.2/ref/rrefjdbclimit.htmlここで説明するように、あなたもlimitキーワードを使用することができますので、あなたのクエリが交互に

PreparedStatement statement = con.prepareStatement("select * from TABLENAME OFFSET ? ROWS FETCH NEXT 1000 ONLY"); 
statement.setInt(1, firstrow); 
ResultSet rs = statement.executeQuery(); 

String query = "select * from TABLENAME OFFSET %d ROWS FETCH NEXT 1000 ONLY"; 
String.format(query, firstrow); 

様またはプリペアドステートメントを使用して、ものになるだろう http://www.toadworld.com/platforms/oracle/b/weblog/archive/2016/01/23/oracle-12c-enhanced-syntax-for-row-limiting-a-k-a-top-n-queries

上または 最初のリンクを参照してくださいクエリは次のようになります

String query = "select * from TABLENAME { LIMIT 1000 OFFSET %d }"; 
String.format(query, firstrow); 
+0

答えが「役に立たない」理由についてフィードバックを得られない場合、何がダウン投票のポイントですか? – bdrx

4

Oracleでページネーションを実装する通常の方法は、アナリティック・ウィンドウ機能を使用することです。 row_numberと、行の順序を定義するORDER BY節。分析関数を使用した問合せは、必要な行番号を問い合せるインライン・ビュー(または「ウィンドウ」)にラップされます。

select rs.* from 
    (select t.*, 
    row_number() over (order by column_to_sort_by) as row_num 
    from my_table t 
) rs 
where rs.row_num >= 1 and rs.row_num < 1001 
order by rs.row_num 

A JDBCの実装は、次のようになります:

public void queryWithPagination() throws SQLException { 
    String query = "select rs.* from" 
     + " (select t.*," 
     + " row_number() over (order by column_to_sort_by) as row_num" 
     + " from my_table t" 
     + ") rs" 
     + " where rs.row_num >= ? and rs.row_num < ?" 
     + " order by rs.row_num"; 

    final int pageSize = 1000; 
    int rowIndex = 1; 

    try (PreparedStatement ps = myConnection.prepareStatement(query)) { 

     do { 
     ps.setInt(1, rowIndex); 
     ps.setInt(2, rowIndex + pageSize); 
     rowIndex += pageSize; 
     } while (handleResultSet(ps, pageSize)); 
    } 
} 

private boolean handleResultSet(PreparedStatement ps, final int pageSize) 
     throws SQLException { 
    int rows = 0; 
    try (ResultSet rs = ps.executeQuery()) { 
     while (rs.next()) { 
      /* 
      * handle rows here 
      */ 
      rows++; 
     } 
    } 
    return rows == pageSize; 
} 

注表はしばらく変わらない必要があることをここで(column_to_sort_byによる発注)my_tableから最初の1000行を照会例です。ページングがさまざまなクエリの実行で正しく動作するように読み込みます。

テーブル内にメモリが不足している行がたくさんある場合は、一部のページを読み込んだ後にリストをパージ/シリアル化する必要があります。

EDIT:

行の順序は、その後、全くあなたには関係していない場合 - あなたは、おそらく改ページを必要としない、そして最速の解決策 - @bdrxは彼の答えに言及してSELECTWHEREの条件を付けずにテーブルをクエリすることになります。提案するとおり、スループットを向上させるために、ステートメントのフェッチサイズをより大きな値に調整することができます。