JDBC批量插入
最近專案中有用到JDBC技術,存在大量資料要進行插入,通過研究採用批量插入速度快的不是一點點。下面簡單比較了一下普通插入與批量插入5W條資料的時間效率。
常規插入:耗時12952ms
public static void normalInsert() throws SQLException { long start = System.currentTimeMillis(); Connection conn = getConnection(); PreparedStatement ps = null; for (int i=0;i < 50000;i++){ String sql = "insert into xxx values (?,'1','1')"; ps = conn.prepareStatement(sql); ps.setString(1, i+""); ps.execute(); ps.close(); } long end = System.currentTimeMillis(); System.out.println(end - start); }
批量插入:耗時930ms
public static void batchInsert() throws SQLException { long start = System.currentTimeMillis(); Connection conn = getConnection(); conn.setAutoCommit(false); PreparedStatement ps = null; String sql = "insert into xxx values (?,'1','1')"; ps = conn.prepareStatement(sql); // 批量插入時ps物件必須放到for迴圈外面 for (int i=0;i < 50000;i++){ ps.setString(1, i+""); ps.addBatch(); // 每1000條記錄插入一次 if (i % 1000 == 0){ ps.executeBatch(); conn.commit(); ps.clearBatch(); } } // 剩餘數量不足1000 ps.executeBatch(); conn.commit(); ps.clearBatch(); long end = System.currentTimeMillis(); System.out.println(end - start); }
顯而易見,這還是表結構簡單,插入資料就相差十倍多。
oracle插入150W耗時3分鐘;刪除52秒。
truncate清空表,速度超快;delete刪除比較慢,可以加條件;刪除150w資料truncate只要2秒,而delete可能要差不多1分鐘
truncate table xxx; delete from xxx;
常見SQL錯誤:
1)Oracle資料庫中開啟的遊標最大數為一定值,預設情況下是300,當代碼到第二步時,迴圈中一個PreparedStatement佔用了一個數據庫遊標,執行的迴圈超過這個數時就會產生遊標數目溢位錯誤。解決辦法:每次執行完PreparedStatement,都將PreparedStatement.close()下,釋放掉這個資源就好了
Exception in thread "main" java.sql.SQLException: ORA-00604: 遞迴 SQL 級別 1 出現錯誤
ORA-01000: 超出開啟遊標的最大數
ORA-00604: 遞迴 SQL 級別 1 出現錯誤
ORA-01000: 超出開啟遊標的最大數
ORA-01000: 超出開啟遊標的最大數
2)java.sql.SQLException:ORA-00054;資源正忙,但指定以NOWAIT方式獲取資源,或者超時失敗
原因:資料庫中存在未提交的記錄
3)java.sql.SQLException 索引中丟失in或out引數
原因:SQL語句有問題
解決:jdbc進行欄位拼接插入操作時,為string型別的加上單引號
另外,用prepareStatement.setString(1, 欄位值),可以防止欄位值有單引號而破壞sql問題
4)java.sql.BathUpdateException:ORA-01461;僅能繫結要插入LONG列的LONG值
原因:由於要插入的欄位長度超出了資料庫中表定義的欄位長度
--------------------------補充-----------------------------------
varchar2是Oracle提供的特定資料型別
varchar2(10)一般情況最多存5個漢字,10個字元。具體要看資料庫使用的字符集:GBK(漢字2位元組;英文1個;Oracle安裝預設GBK編碼格式);UTF-8(漢字3位元組,英文1個)
一般頁面做輸入字串長度校驗時,以資料庫設計欄位最大長度/3作為最大長度
nvarchar(10)可以存10個漢字,10個字元
當長度大於4000的時候就應該用CLOB,因為oracle的varchar2最多4000個字元
5)ORA-24816:在實際的LONG或LOB列之後提供了擴充套件的非LONG繫結資料
原因:這個問題很奇怪,就算沒有LONG型別的資料,全部都是VARCHAR2和CLOB在操作資料庫更新的時候一直報這個錯誤
解決:歪打正著,調整了一下各種更新欄位位置,將放在前面的CLOB型別放在後面,就不報錯了