postgresqlクエリの大きなResultSet
-
05-07-2019 - |
質問
postgresqlデータベースのテーブルに対してクエリを実行しています。データベースはリモートマシン上にあります。テーブルには、postgresql パーティショニング機能を使用した約30個のサブテーブルがあります。 。
クエリは約180万行の大きな結果セットを返します。
Spring jdbcサポートを使用するコードでは、メソッド JdbcTemplate.query ですが、私の RowCallbackHandler は呼び出されていません。
私の最善の推測は、postgresql jdbcドライバー(バージョン8.3-603.jdbc4を使用)がコードを呼び出す前に結果をメモリに蓄積していることです。 fetchSize構成でこれを制御できますが、試してみましたが、何も変わりません。これはpostgresqlのマニュアル推奨として行いました。
このクエリは、Oracle XEを使用したときに正常に機能しました。しかし、Oracle XEでは使用できないパーティション機能のために、postgresqlに移行しようとしています。
私の環境:
- Postgresql 8.3
- Windows Server 2008 Enterprise 64ビット
- JRE 1.6 64ビット
- 春2.5.6
- Postgresql JDBC Driver 8.3-603
解決
カーソルを使用してデータを取得するには、ResultSet.TYPE_FORWARD_ONLY(デフォルト)のResultSet型を設定し、フェッチサイズの設定に加えてfalseに自動コミットする必要があります。リンク先のドキュメントで参照されていますが、これらの手順を実行したことを明示的に言及していません。
PostgreSQLのパーティションスキームに注意してください。オプティマイザで非常に恐ろしいことを実際に行い、あるべきではないところに大規模なパフォーマンスの問題を引き起こす可能性があります(データの詳細に依存します)。いずれにせよ、行は180万行のみですか?適切に索引付けされている場合、サイズのみに基づいてパーティション化する必要がある理由はありません。
他のヒント
私は、180万行を同時に必要とするアプリのクライアントが1つもないことに賭けています。結果を小さな断片に分割し、ユーザーがそれらを繰り返し処理する機会を与える賢明な方法を考える必要があります。
それがGoogleの仕事です。検索を行うと、数百万件のヒットが発生する可能性がありますが、最初のページで必要なものが見つかると考えて、一度に25ページが返されます。
クライアントではなく、結果が何らかの方法で処理されている場合、データベースにこれらすべての行を処理させ、結果を返すことをお勧めします。中間層で計算を行うためだけに180万行を返すことは意味がありません。
どちらも当てはまらない場合は、実際に問題が発生しています。考え直します。
後の回答を読んだ後、バッチでクランチするか、リアルタイムで計算し、トランザクションシステムの一部ではないテーブルに保存する必要があるレポートソリューションのように思えます。移動平均を計算するために180万行を中間層に持ってくることはできません。
自分の向きを変えることをお勧めします。それをレポートソリューションとして考え始めてください。
fetchSizeプロパティは、 postgresマニュアルで説明されているように機能しました。
私の間違いは、プリペアドステートメントで使用されている接続ではない接続プールからの接続にauto commit = falseを設定していたことです。
すべてのフィードバックに感謝します。
上記のすべてを実行しましたが、最後の1つが必要です。呼び出しがトランザクションにラップされていることを確認し、トランザクションを読み取り専用に設定して、ロールバック状態が不要になるようにします。
これを追加しました: @Transactional(readOnly = true)
乾杯。