Oracle存儲過程處理大批量數據性能測試

通過此次的大批量數據性能測試,還會間接的給大家分享一個知識點,Oracle存儲過程如何處理List集合的問題,廢話不多說了,老規矩直接上代碼!!!

首先要做的,想必大家應該猜到了。。。建表!

create table tab_1
(
       id varchar(100) primary key,
       name varchar(100),
       password varchar(100)
)



第一步:
create or replace type tab_one as object(
       id varchar2(200),
       name varchar2(200),
       password varchar2(200)
)

第二步:

create or replace type tab_ones as table of tab_one

第三步:

create or replace procedure test7(i_orders in tab_ones)
as
orders tab_one;
begin
     FOR idx in i_orders.first..i_orders.count loop
         orders:=i_orders(idx);
         insert into tab_1
         (id,name,password)
         values
         (orders.id,orders.name,orders.password);
     end loop;
     exception when others then
     raise;

end test7;


測試代碼:
public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
          Class.forName(driver);
          conn = DriverManager.getConnection(url,name,password);
          CallableStatement proc = null;
          List<Tab_One_Bean> orderList = new ArrayList<Tab_One_Bean>(); 
          String date=DateUtils.getDate_time();
          System.out.println("開始:"+date); 
          for(int i=0;i<100000;i++){  
              System.out.println("第"+i+"個");
              orderList.add(new Tab_One_Bean("第"+i+"個","新增用戶"+i,i+"@126.com"));  
          }
          StructDescriptor recDesc = StructDescriptor.createDescriptor("TAB_ONE", conn);  
          //這裏注意下TAB_ONE在創建時是小寫但編譯後在Types顯示的是大寫的
          ArrayList<STRUCT> pstruct = new ArrayList<STRUCT>();  
          for (Tab_One_Bean ord:orderList) {                  
              Object[] record = new Object[3];  
              record[0] = ord.getId();  
              record[1] = ord.getName();
              record[2] = ord.getPassword();
              STRUCT item = new STRUCT(recDesc, conn, record);                
              pstruct.add(item);  
          } 
            ArrayDescriptor tabDesc = ArrayDescriptor.createDescriptor("TAB_ONES", conn);            
//這裏注意下TAB_ONES在創建時是小寫但編譯後在Types顯示的是大寫的            
          ARRAY vArray = new ARRAY(tabDesc, conn, pstruct.toArray());
          proc = conn.prepareCall("{call test7(?)}");       
          proc.setArray(1, vArray);                 
          proc.execute();  
          conn.commit();
          System.out.println("開始:"+date+"  結束:"+DateUtils.getDate_time());
        }
        catch (SQLException ex2) {
          ex2.printStackTrace();
        }
        catch (Exception ex2) {
          ex2.printStackTrace();
        }
        finally{
          try {
            if(rs != null){
              rs.close();
              if(stmt!=null){
                stmt.close();
              }
              if(conn!=null){
                conn.close();
              }
            }
          }
          catch (SQLException ex1) {
          }
        }
     }  

【主意點:】
這裏寫圖片描述

我這裏測試了100000條數據量,運行結果:
...
第99989個
第99990個
第99991個
第99992個
第99993個
第99994個
第99995個
第99996個
第99997個
第99998個
第99999個
開始:2017-09-08 16:18:07  結束:2017-09-08 16:18:18

最快的一次用了9秒!


**繼續優化以上代碼:修改的代碼,直接註釋了**

第一步:【建議使用這種方式】
public class Tab_One_Bean1 implements ORAData{
    private String id;
    private String name;
    private String password;
    public static final String ORACLE_TYPE_NAME = "TAB_ONE";
    protected MutableStruct struct;  
    static int[] sqlType = { OracleTypes.VARCHAR, OracleTypes.VARCHAR,OracleTypes.VARCHAR };  
    static ORADataFactory[] factory = new ORADataFactory[sqlType.length];  
    public Tab_One_Bean1() {  
        struct = new MutableStruct(new Object[sqlType.length], sqlType, factory);  
    }  
    public Tab_One_Bean1(String id,String name,String password){
        this();//注意這裏的this()必須加上,不加會報錯,具體錯誤看下面截圖
        this.id=id;
        this.name=name;
        this.password=password;
    }
    @Override
    public Datum toDatum(Connection conn) throws SQLException {
        System.out.println("id:"+this.id+" name:"+this.name+" password: "+this.password);
        struct.setAttribute(0, this.id);
        struct.setAttribute(1, this.name);
        struct.setAttribute(2, this.password);
        return struct.toDatum(conn, ORACLE_TYPE_NAME);
    }

}

【注意】這裏的this()必須加上,不加會報以下錯誤:

開始:2017-09-08 16:49:29
id:0個 name:新增用戶0 password: 0@126.com
java.lang.NullPointerException
    at com.util.oracleutils.Tab_One_Bean1.toDatum(Tab_One_Bean1.java:32)
    at oracle.sql.STRUCT.toSTRUCT(STRUCT.java:603)
    at oracle.jdbc.oracore.OracleTypeADT.toDatum(OracleTypeADT.java:241)
    at oracle.jdbc.oracore.OracleTypeADT.toDatumArray(OracleTypeADT.java:302)
    at oracle.jdbc.oracore.OracleTypeUPT.toDatumArray(OracleTypeUPT.java:117)
    at oracle.sql.ArrayDescriptor.toOracleArray(ArrayDescriptor.java:1517)
    at oracle.sql.ARRAY.<init>(ARRAY.java:117)
    at com.util.oracleutils.CallableStatementOracleUtils.main(CallableStatementOracleUtils.java:55)

這裏寫圖片描述


public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
          Class.forName(driver);
          conn = DriverManager.getConnection(url,name,password);
          CallableStatement proc = null;
//        List<Tab_One_Bean> orderList = new ArrayList<Tab_One_Bean>(); 
          List<Tab_One_Bean1> orderList = new ArrayList<Tab_One_Bean1>(); 
          String date=DateUtils.getDate_time();
          System.out.println("開始:"+date); 
          for(int i=0;i<100000;i++){  
//            System.out.println("第"+i+"個");
//            orderList.add(new Tab_One_Bean("第"+i+"個","新增用戶"+i,i+"@126.com"));  
          orderList.add(new Tab_One_Bean1("第"+i+"個","新增用戶"+i,i+"@126.com"));
          }
//        StructDescriptor recDesc = StructDescriptor.createDescriptor("TAB_ONE", conn);  //這裏注意下TAB_ONE在創建時是小寫但編譯後在Types顯示的是大寫的
//        ArrayList<STRUCT> pstruct = new ArrayList<STRUCT>();  
//        for (Tab_One_Bean ord:orderList) {                  
//            Object[] record = new Object[3];  
//            record[0] = ord.getId();  
//            record[1] = ord.getName();
//            record[2] = ord.getPassword();
//            STRUCT item = new STRUCT(recDesc, conn, record);                
//            pstruct.add(item); 
//        }             
          ArrayDescriptor tabDesc = ArrayDescriptor.createDescriptor("TAB_ONES", conn);//這裏注意下TAB_ONES在創建時是小寫但編譯後在Types顯示的是大寫的            
          //ARRAY vArray = new ARRAY(tabDesc, conn, pstruct.toArray());
          ARRAY vArray = new ARRAY(tabDesc, conn, orderList.toArray());
          proc = conn.prepareCall("{call test7(?)}");       
          proc.setArray(1, vArray);                 
          proc.execute();  
          conn.commit();
          System.out.println("開始:"+date+"  結束:"+DateUtils.getDate_time());
        }
        catch (SQLException ex2) {
          ex2.printStackTrace();
        }
        catch (Exception ex2) {
          ex2.printStackTrace();
        }
        finally{
          try {
            if(rs != null){
              rs.close();
              if(stmt!=null){
                stmt.close();
              }
              if(conn!=null){
                conn.close();
              }
            }
          }
          catch (SQLException ex1) {
          }
        }
     }  


繼續測試10萬條數據,運行結果:
開始:2017-09-08 16:56:32
開始:2017-09-08 16:56:32  結束:2017-09-08 16:56:42


還有一種批量處理的方法進行和存儲過程方法對比下哈:
public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, name, password);

            String date = DateUtils.getDate_time();
            System.out.println("開始:" + date);
            List<String> lis = new ArrayList<>();
            for (int i = 0; i < 10000; i++) {
                lis.add("insert into tab_1 (id,name,password)values('第" + i + "位','新增用戶" + i + "','" + i + "@126.com')");
            }
            conn.setAutoCommit(false);
            pst = conn.createStatement();
            for (int i = 0; i < lis.size(); i++) {
                System.out.println("第:" +i);
                pst.addBatch(lis.get(i).toString());
            }
            pst.executeBatch();
            conn.commit();
            System.out.println("開始:" + date + "  結束:" + DateUtils.getDate_time());
        } catch (SQLException ex2) {
            ex2.printStackTrace();
        } catch (Exception ex2) {
            ex2.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                    if (stmt != null) {
                        stmt.close();
                    }
                    if (conn != null) {
                        conn.close();
                    }
                }
            } catch (SQLException ex1) {
            }
        }
    }
運行結果:
...
第:9990
第:9991
第:9992
第:9993
第:9994
第:9995
第:9996
第:9997
第:9998
第:9999
開始:2017-09-08 17:52:24  結束:2017-09-08 17:53:46


使用addBatch()方法批量處理數據測試10000條數據用時82秒!
存儲過程10000條數據用時1秒!!!
存儲過程再次測試100000條數據用時8秒!!!

我的技術羣這裏給大家分享下:472148690 問題可以在羣裏諮詢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章