2

JDBCを使用して大量のデータをPostgSQLデータベースに配置するexecuteBatchステートメントとPreparedステートメントの両方に関連する奇妙な問題があります。executeBatchを使用して、毎回50,000個のステートメントをデータベースに送信しています。

バッチの実行とプリペアドステートメントが機能していることはわかっています。一部のデータがデータベースに流れ込んでいます。プリペアドステートメントは

  INSERT INTO time ( time_id, log_id, phenomenon_time, qc_phenomenon_time )
  SELECT nextval( 'time_seq' ), ?, ?, ?

これを実行バッチで使用すると、データはデータベースにあります。

次のプリペアドステートメントを使用する場合、

  INSERT INTO result_3d ( result_3d_id, time_id, variable_id, value, qc_value ) 
  SELECT nextval( 'result_3d_seq' ), ( SELECT t.time_id 
                                       FROM time t 
                                       WHERE t.log_id = ? 
                                       AND t.phenomenon_time = ? ), ?, ?, ?

バッチの実行では、データベースにデータがありません。私はデータベースロギングをオンにして、最初はすべてを見つけましたが、2番目は何も見つけませんでした。2番目のプリペアドステートメントは最初のデータに依存していますが、データベースは2番目のステートメントさえ認識していません。

スローされる例外はありません。唯一の不思議なことに、2番目のプリペアドステートメントの場合、返される配列のサイズはゼロです。実行バッチはすぐに戻ります。2番目のプリペアドステートメントのサブクエリは許可されていますか?

PostgreSQLv8.3.19データベースに対するJDBCドライバーとしてpostgres-9.1-901.jdbc4.jarを使用しています。

助けてください。

4

2 に答える 2

3

私が説明した症状は、バッチの実行またはプリペアドステートメントとは何の関係もないので、私は自分の質問に答えるつもりです。いくつかのリファクタリング中に、私は重要なステートメントを省略しました。

this.preparedStatement.addBatch();

だからこれは私の悪いです。症状は、ステートメントが欠落しているコードの動作を美しく説明しています。

コメントのご尽力に感謝いたします。研究すべき新しい分野を私に与えてくれた人もいます。アーウィンに感謝します。

于 2012-06-25T10:05:46.813 に答える
2

JDBCドライバーはわかりませんが、バージョン9.1を使用して、古いPostgreSQL8.3.19に接続しているのではないかと疑っています。PostgreSQLを9.1にアップグレードすると、問題が解決する場合があります。

time.time_id一般に、列を列result_3d.result_3d_idとして定義した場合serial(おそらくそうする必要があります)、またはこれらの列のDEFAULT値をそれぞれのシーケンスで手動で設定した場合は、シーケンスnextval()からIDをフェッチする必要はありません。値は自動的に入力されます。

2番目のプリペアドステートメントのサブクエリは許可されていますか?

はい、それは-原則としてです。ただし、複数の行を返すことはありません。一意性を保証する(t.log_id, t.phenomenon_time)か、以下を追加する必要がありLIMIT 1ます。

(SELECT t.time_id 
 FROM time t 
 WHERE t.log_id = ? 
 AND t.phenomenon_time = ?
 LIMIT 1)

PostgreSQL 9.1を使用すると、2つのコマンドをデータ変更CTEINSERTと一緒にチェーンできます。これにより、かなり高速になり、サブクエリを最初に作成する必要がなくなります。

WITH data (log_id, phenomenon_time, qc_phenomenon_time
          ,variable_id, value, qc_value ) AS (
    VALUES(?, ?, ?, ?, ?, ?)  -- cast to appropriate types!
    )
    , i AS (
    INSERT INTO time (log_id, phenomenon_time, qc_phenomenon_time)
    SELECT log_id, phenomenon_time, qc_phenomenon_time
    FROM   data
    RETURNING time_id, log_id, phenomenon_time 
    )
INSERT INTO result_3d (time_id, variable_id, value, qc_value) 
SELECT i.time_id, d.variable_id, d.value, d.qc_value
FROM   data d
JOIN   i USING (log_id, phenomenon_time);

これらすべてが根本的な問題を解決する場合としない場合がありますが、解決する可能性は十分にあります。

私の最初の考えは、根本的な問題は並行性の問題である可能性があるということでした。つまり、最初の問題INSERTがコミットされる前に2番目の問題が開始されます。しかし、データベースが2番目の呼び出しさえ認識しない場合は、ここで他の何かが機能している必要があります。

于 2012-06-24T03:46:31.690 に答える