2009-03-13 5 views
15

大量のID(整数)を取得するためのクエリを実行しています。 ResultSetを何百回も繰り返し実行するのではなく、すべてをArrayListにコピーするのではなく、単にArrayListとしてすべてを取得する方法がありますか?JDBC ResultSetをArrayListとして取得するにはどうすればよいですか?

私はResultSetが反復されることになっていると理解していますが、基本的な実装ではキャッシングがある可能性があるので、私の状況ではすべてのIDをすぐに必要とします。私はFetchSizeを大きな数に設定できますが、それでもIDを1つずつ取得する必要があります。

明確化:これを行う理由はパフォーマンスです。プロファイリングでは、ResultSet.next()、ResultSet.getInt()およびArrayList.add()を何百回も実行するとかなりの時間がかかることがわかります。私はデータベース(私は、Javaで書かれているH2を使用している)はおそらく、メモリ内のどこかに配列やリストを持っていることを理解しているので、私はそれを私に直接コピーする代わりにResultSetの反復インタフェース。

+1

おそらく数百万の整数を扱うのには長い時間がかかります。代わりにint []またはプリミティブList-likeが必要ですか?おそらくint/Listとして直接実装されていないかもしれません。 –

+0

int []またはListはどちらも問題ありません。私は基本的にちょうどデータベースに言う方法を探しています:キャッシング/怠惰な読み込み/等を忘れて、できるだけ早く私にデータを与えてください:) – Deckard

+1

プロファイルを持ち、パフォーマンスの問題がどこにあるかを見てください。 (OracleはResultSet、IIRCで列配列メソッドを取得していますが、それはH2にとって重要ではありません) –

答えて

6

コードをメソッドに挿入します。それは...メソッドを呼び出すために私の頭の上オフ

非常に簡単です:

完了
List<Integer> ids = readInts(myStatemnet); 

public static List<Integer> readInts(
    PreparedStatement statement 
) throws SQLException { 
    ResultSet results = statement.executeQuery(); 
    try { 
     assert results.getMetaData().getColumnCount() == 1; 

     List<Integer> ints = new ArrayList<Integer>(); 
     while (results.next()) { 
      ints.add(Integer.valueOf(results.getInt(1))); 
     } 
     return ints; 
    } finally { 
     results.close(); 
    } 
} 

は、それからちょうどとしてそれを呼び出します。

+2

これは、データをループしているパフォーマンスに役立ちません。私は彼がちょうどそれをダンプしたいと思う。 –

+1

どのようにデータをループせずに "ダンプする"でしょうか? (質問の最後の段落はオリジナルではありませんでした。) –

17

Apache DbUtilsライブラリを使用すると、ResultSetをマップのリストとして簡単に返すことができます。

public List query(String query) { 
    List result = null; 
    try { 
     QueryRunner qrun = new QueryRunner(); 
     result = (List) qrun.query(connection, query, new MapListHandler()); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
    return result; 
} 
+0

これはJDBC自体の性能を上回っていませんか?合意した、それはより便利に見えますが、確かに、それは速くはありません...? –

+0

DbUtilsはヘルパーライブラリなので、まだJDBCを使用しています。彼らのサイトでDbUtilsを使う利点のいくつかを見てみましょう。 http://commons.apache.org/dbutils/ – Mark

+0

私は理解していますが、あなたが答えた後、OPは質問を変更したようです。彼らはパフォーマンスを向上させるために、JDBC APIをバイパスする方法を探していました... –

5

あなたの問題は100と

java.sql.Statement.setFetchSize(int) 

実験、1000年、10000、とそれを実行する前にパフォーマンスの低下、チューニングの文である場合。これは、の原因である可能性があり、不必要なラウンドトリップを回避しますがあなたが言った遅さ。

また、ArrayList.add()は、新しい配列を作成してそこにすべてのデータをコピーするので、内部配列のサイズを何度も変更する必要がある場合は遅くなることがあります。代わりにLinkedListを試してみてください。

+0

使用するフェッチサイズがわかっている場合は、内部配列の初期サイズを同じ量としてArrayListコンストラクタで宣言することもできます。 –

+1

@Daddy 私が理解したところでは、質問の著者はすべての返されたIDを単一のリストに追加していました。つまり、fetchsizeだけでなく、結果セットのフルサイズの配列を作成しない限り、あなたの提案は実際には役に立ちません。 – Antonio

+1

@Deckard、この問題はまだ受け入れられた答えはありません、あなたはこの問題を解決しましたか? – malatesh

関連する問題