簡體   English   中英

ExecuteBatch和預准備語句的奇怪行為

[英]Curious behaviour with ExecuteBatch and Prepared Statements

我有一個奇怪的問題,涉及同時使用JDBC將executeBatch和Prepared Statements放置到PostgSQL數據庫中的大量數據。 我正在使用executeBatch每次向數據庫發送50,000條語句。

我知道執行批處理和准備好的語句正在工作; 一些數據正在進入數據庫。 准備好的語句是

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

並將其與execute batch一起使用,可以在數據庫中找到數據。

使用以下准備好的語句時,

  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 = ? ), ?, ?, ?

執行批處理時,數據庫中沒有數據。 我什至沒有打開數據庫日志記錄,第一次發現了所有內容,而第二次卻什么也沒有。 第二條准備好的語句依賴於第一條語句的數據,但數據庫甚至看不到第二條語句。

沒有異常被拋出。 唯一奇怪的是,對於第二條准備好的語句,返回的數組的大小為零。 批處理批次立即返回。 第二條准備好的語句中的子查詢是否被允許?

我使用postgres-9.1-901.jdbc4.jar作為針對PostgreSQL v8.3.19數據庫的JDBC驅動程序。

請幫忙。

我不知道JDBC驅動程序,但是您使用9.1版並連接到過時的PostgreSQL 8.3.19看起來很可疑。 將PostgreSQL升級到9.1可能會解決您的問題。

通常,如果您已將time.time_idresult_3d.result_3d_id列定義為serial列(可能應該如此),或者已將這些列的DEFAULT值手動設置為各自序列上的nextval() ,則不需要從序列中獲取id。 值將自動填寫

第二條准備好的語句中的子查詢是否被允許?

是的,原則上是。 但是它可能永遠不會返回超過一行 您必須保證(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時,您可以將兩個INSERT命令與一個可修改數據的CTE鏈接在一起,這應該會更快一些,並且避免了以子查詢開頭的需求:

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之前啟動了第二個INSERT 但是,如果數據庫甚至看不到第二個調用,則這里還有其他工作。

我要回答自己的問題,因為我描述的症狀與“執行批處理”或“准備好的語句”無關。 在進行一些重構時,我沒有發表重要的聲明。

this.preparedStatement.addBatch();

所以這是我的壞事。 這些症狀用缺少的語句很好地描述了代碼的行為。

感謝您的意見。 有些給了我新的學習領域。 謝謝歐文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM