JDBC寫資料到檔案中再Copy到postgresql中
阿新 • • 發佈:2019-02-03
經過測試,大概寫入12萬條資料2秒+左右。
程式碼如下:
package com.nsfocus.bsaips.main; import com.alibaba.fastjson.JSONObject; import com.nsfocus.bsaips.util.RemoteDBUtil; import org.postgresql.copy.CopyManager; import org.postgresql.core.BaseConnection; import java.sql.*; import java.util.ArrayList; import java.io.*; import java.util.List; import java.util.UUID; public class Test { public String writeFile(List<JSONObject> list){ FileWriter out = null; String filePath = "/tmp/"+UUID.randomUUID(); try{ out = new FileWriter(new File(filePath)); for(int i=0;i<list.size();i++){ Object[] objs = list.get(i).values().toArray(); for(int j=0;j<objs.length;j++){ if(objs[j] == null){ out.write("null"); }else{ out.write(String.valueOf(objs[j])); } if(j != objs.length - 1){ out.write(","); } } if(i != list.size() - 1){ out.write("\n"); } } out.flush(); }catch(Exception ex){ ex.printStackTrace(); }finally{ if(out != null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } return filePath; } public void copyTest(String tablename,List<JSONObject> list){ Connection conn = null; CopyManager copyManager = null; FileReader reader = null; try{ long starttime = System.currentTimeMillis(); String filePath = writeFile(list); conn = RemoteDBUtil.getInstance("ip",5432,"dbname","username","password").getConnection(); copyManager = new CopyManager((BaseConnection)conn); reader = new FileReader(new File(filePath)); copyManager.copyIn("copy "+tablename+" from stdin delimiter as ',' NULL as 'null'",reader); long endtime = System.currentTimeMillis(); System.out.println(endtime-starttime); }catch(Exception ex){ ex.printStackTrace(); }finally{ if(reader != null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } public static void main(String[] args){ List<JSONObject> list = new ArrayList<JSONObject>(); for(int i=0;i<120000;i++){ JSONObject jsonObject = new JSONObject(); jsonObject.put("id",i); jsonObject.put("testname","aaaa"); list.add(jsonObject); } new Test().copyTest("copytest", list); } }
然後,請記住COPY完成後一定要刪除檔案。
刪除檔案的程式碼:
File file = new File(filePath); if(file.exists()){ file.delete(); }
另外,再記錄一個小插曲:
居然有張表據說最多每次插入3000條資料(100*30),要不然時間就會變長而且磁碟IO很高。我的眼鏡都快掉到地上摔碎了,一度懷疑自己進入了平行宇宙。
後來一看,表上有個主鍵約束,而寫入的資料中是包含主鍵這個欄位的,也就是每條寫入的資料資料庫都需要檢測唯一性。而當時,表中的資料已經600w+條了。不用會懷疑入庫速度為啥如此之慢了。
而主鍵欄位本身使用UUID生成的(網絡卡+毫米級時間戳+隨機數)絕對保證唯一的,所以根本不需要資料庫來保證唯一性。把約束去掉,入庫速度就坐上飛機了。