【Oracle/Java】多表插删数据单多线程比较
源码下载:https://files.cnblogs.com/files/xiandedanteng/OracleAccessComparison20191117.rar
做这个比较工程初衷是:我在单位试验一个单线程删21张表和多线程删21张表比较方案,发现单线程从八百五十万数据需要5分钟上下,多线程(一张表一个线程,为此还把MaxActive调大了)却需要9分钟左右,尤其是删其中两张两百万级别的大表的两个线程总不结束。这个结果是和我以往的多线程比单线程快的观念是违背的,我想了想,这个有违常识的结果是因为单位的Oracle是建立在虚拟机上的有关,在家里的实际环境测试结果该符合常识。于是就建立了这个工程,从而证实常识还是对的。一般情况确实是多线程比单线程快,特定环境的另当别论。
下面把代码贴出来以供日后参考,如果它对你也有帮助那就再好不过了。
数据库连接参数类:
package com.hy; /** * 数据库连接参数 * @author 逆火 * * 2019年11月16日 上午8:09:24 */ public final class DBParam { public final static String Driver = "oracle.jdbc.driver.OracleDriver"; public final static String DbUrl = "jdbc:oracle:thin:@127.0.0.1:1521:orcl"; public final static String User = "ufo"; public final static String Pswd = "1234"; }
用于建立十六章表的类:
package com.hy; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.log4j.Logger; /** * 此类用于管理表的创建和销毁 * @author 逆火 * * 2019年11月16日 下午5:40:22 */ public class TableHandler { private static Logger log = Logger.getLogger(TableHandler.class); private String[] tablenames= { "TestTB01", "TestTB02", "TestTB03", "TestTB04", "TestTB05", "TestTB06", "TestTB07", "TestTB08", "TestTB09", "TestTB10", "TestTB11", "TestTB12", "TestTB13", "TestTB14", "TestTB15", "TestTB16", }; /** * Get the create table ddl of a table * @param table * @return */ private String getCreateTbSql(String table) { StringBuilder sb=new StringBuilder(); sb.append("CREATE TABLE "+table); sb.append("("); sb.append("\"ID\" NUMBER(8,0) not null primary key,"); sb.append("\"NAME\" NVARCHAR2(60) not null,"); sb.append("\"AGE\" NUMBER(3,0) DEFAULT 0 not null ,"); sb.append("\"CREATEDTIME\" TIMESTAMP (6) not null"); sb.append(")"); return sb.toString(); } /** * Judge if a table is exist * @param table * @param stmt * @return * @throws SQLException */ private boolean isTableExist(String table,Statement stmt) throws SQLException { String sql="SELECT COUNT (*) as cnt FROM ALL_TABLES WHERE table_name = UPPER('"+table+"')"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int count = rs.getInt("cnt"); return count==1; } return false; } /** * Crate tables */ public void createTables() { Connection conn = null; Statement stmt = null; try{ Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); int i=0; for(String table:tablenames) { i++; String sql=getCreateTbSql(table); stmt.executeUpdate(sql); if(isTableExist(table,stmt)) { log.info("#"+i+" "+table+" created."); } } } catch (Exception e) { System.out.print(e.getMessage()); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { System.out.print("Can't close stmt/conn because of " + e.getMessage()); } } } /** * Remove all the tables */ public void dropTables() { Connection conn = null; Statement stmt = null; try{ Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); int i=0; for(String table:tablenames) { i++; String sql="drop table "+table; stmt.executeUpdate(sql); if(isTableExist(table,stmt)==false) { log.info("#"+i+" "+table+" dropped."); } } } catch (Exception e) { System.out.print(e.getMessage()); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { System.out.print("Can't close stmt/conn because of " + e.getMessage()); } } } /** * Kick start * @param args */ public static void main(String[] args) { TableHandler th=new TableHandler(); th.createTables(); } }
单线程插表类:
package com.hy.insert.singlethread; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import com.hy.DBParam; import com.hy.TableHandler; /** * 此类用于向各表批量插入数据(单线程模式) * @author 逆火 * * 2019年11月16日 下午6:33:01 */ public class BatchInserter { private static Logger log = Logger.getLogger(TableHandler.class); private final int BatchSize=250;// 一次性插入记录数 private final int TotalInsert=100000;// 单表插入总记录数 // 要插入的表数组 private final String[][] tableArray= { {"TestTB01:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB02:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB03:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB04:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB05:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB06:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB07:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB08:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB09:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB10:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB11:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB12:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB13:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB14:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB15:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB16:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, }; /** * 批量插入 */ public void batchInsert() { Connection conn = null; Statement stmt = null; try{ Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); System.out.println("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"..."); int index=1; for(String[] innerArr:tableArray) { long startTime = System.currentTimeMillis(); String tableName=innerArr[0].split(":")[0]; int count=Integer.parseInt(innerArr[0].split(":")[1]); truncateTable(tableName,conn,stmt); insertDataToTable(index,tableName,count,innerArr,conn,stmt); if(isAllInserted(count,tableName,stmt)) { long endTime = System.currentTimeMillis(); log.info("#"+index+" "+count+" records were inserted to table:'" + tableName + "' used " + sec2DHMS(startTime,endTime) ); index++; } } } catch (Exception e) { System.out.print(e.getMessage()); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { log.error("Can't close stmt/conn because of " + e.getMessage()); } } } /** * judge if all records are inserted * @param count * @param table * @param stmt * @return * @throws SQLException */ private boolean isAllInserted(int count,String table,Statement stmt) throws SQLException { String sql="SELECT COUNT (*) as cnt FROM "+table; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int cnt = rs.getInt("cnt"); return cnt==count; } return false; } /** * get datetime n seconds before * @param n * @param interval * @return */ private static String getDatetimeBefore(int n,int interval) { try { Calendar now = Calendar.getInstance(); now.add(Calendar.SECOND,-n*interval);//鏃ユ湡鍑忓幓n*10绉� Date newDate=now.getTime(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String retval = sdf.format(newDate); return retval; } catch(Exception ex) { ex.printStackTrace(); return null; } } /** * delete all data in a table quickly * @param tableName * @param conn * @param stmt * @throws SQLException */ private void truncateTable(String tableName,Connection conn,Statement stmt) throws SQLException{ String sql="truncate table "+tableName; stmt.execute(sql); System.out.println("truncated table:"+tableName); } /** * Insert date to a table * @param tbSN * @param tableName * @param count * @param innerArr * @param conn * @param stmt * @throws SQLException */ private void insertDataToTable(int tbSN,String tableName,int count,String[] innerArr,Connection conn,Statement stmt) throws SQLException{ // 寰楀埌瀛楁鍚嶅拰瀛楁绫诲瀷 List<TypeField> typefields=new ArrayList<TypeField>(); for(int i=1;i<innerArr.length;i++) { String temp=innerArr[i]; String[] arrTmp=temp.split(":"); TypeField tf=new TypeField(); tf.type=arrTmp[0]; tf.field=arrTmp[1]; typefields.add(tf); } List<String> fields=new ArrayList<String>(); List<String> values=new ArrayList<String>(); int index=0; for(TypeField tf:typefields) { fields.add(tf.field); values.add("''{"+index+"}''"); index++; } int interval=2*365*24*60*60/count;// 涓ゅ勾鐨勭鏁伴櫎浠ユ�讳釜鏁板嵆涓洪棿闅� index=0; int times=count/BatchSize; for(int i=0;i<times;i++) { StringBuilder sb=new StringBuilder(); sb.append("INSERT ALL "); for(int j=0;j<BatchSize;j++) { index=i*BatchSize+j; sb.append(getInsertSql(tableName,typefields,index,interval)); } sb.append(" select * from dual"); String sql = sb.toString(); //long startTime = System.currentTimeMillis(); stmt.executeUpdate(sql); //long endTime = System.currentTimeMillis(); //System.out.println("#"+tbSN+"-"+i+" "+BatchSize+" records inserted to '"+tableName+"' used " + sec2DHMS(startTime,endTime)); } } /** * get insert sql * @param tableName * @param typefields * @param index * @return */ private String getInsertSql(String tableName,List<TypeField> typefields,int index,int interval) { String currTime=getDatetimeBefore(index,interval); StringBuilder sb=new StringBuilder(); sb.append(" INTO "+tableName+"("); List<String> fields=new ArrayList<String>(); for(TypeField tf:typefields) { fields.add(tf.field); } sb.append(String.join(",",fields)); sb.append(") values("); List<String> values=new ArrayList<String>(); for(TypeField tf:typefields) { if(tf.type.equals("PK")) { //values.add("'"+String.valueOf(index)+"'"); if(tableName.contains("DELIVERY_INFO_HISTORY")) { values.add("'0'"); }else { values.add("'"+String.valueOf(index)+"'"); } }else if(tf.type.equals("CH")) { values.add("'0'"); }else if(tf.type.equals("US")) { values.add("'heyang'"); }else if(tf.type.equals("DT")) { values.add("to_date('"+currTime+"','yyyy-MM-dd HH24:mi:ss')"); } } sb.append(String.join(",",values)); sb.append(")"); String insertSql=sb.toString(); return insertSql; } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } protected static final class TypeField{ String type; String field; } public static void main(String[] args) { BatchInserter mi=new BatchInserter(); long startTime = System.currentTimeMillis(); mi.batchInsert(); long endTime = System.currentTimeMillis(); System.out.println("Time elapsed:" + sec2DHMS(startTime,endTime) ); } }
多线程插表管理器类:
package com.hy.insert.multithread; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; /** * 多线程批量插入管理者 * @author 逆火 * * 2019年11月17日 上午9:19:09 */ public class InsertManager { private static Logger log = Logger.getLogger(InsertManager.class); private final int TotalInsert=100000;// 单表插入总记录数 private List<InsertJobInfo> jobInfos;// 插表信息集合 private long startTime;// Start time // 要插入的表数组 private final String[][] tableArray= { {"TestTB01:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB02:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB03:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB04:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB05:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB06:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB07:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB08:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB09:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB10:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB11:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB12:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB13:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB14:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB15:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB16:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, }; /** * 启动线程进行批量插入 */ public void batchInsert() { startTime=System.currentTimeMillis(); jobInfos=new ArrayList<InsertJobInfo>(); int index=1; for(String[] innerArr:tableArray) { String tableName=innerArr[0].split(":")[0]; int count=Integer.parseInt(innerArr[0].split(":")[1]); new InsertThread(index,tableName,count,innerArr,this).start(); index++; } } /** * Thread report manager "job done." * @param tbSN * @param tableName * @param timeElasped */ public void reportFinished(String tbSN,String tableName,String timeElasped) { jobInfos.add(new InsertJobInfo(tbSN,tableName,timeElasped)); if(jobInfos.size()==tableArray.length) { long endTime = System.currentTimeMillis(); log.info(">>> Insert jobs finished.( time elapsed: " + sec2DHMS(startTime,endTime)+") <<<"); log.info("------------ Details ------------"); for(InsertJobInfo jobInfo:jobInfos) { String raw="{0},{1},{2}"; Object[] arr={jobInfo.tbSn,jobInfo.tableName,jobInfo.timeElapsed}; String line=MessageFormat.format(raw, arr); log.info(line); } log.info("------------ Details ------------"); }else { log.info(jobInfos.size()+" inserters completed their jobs."); } } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } /** * 成员内部类,用来做数据结构 * @author 逆火 * * 2019年11月17日 上午9:22:04 */ protected static final class InsertJobInfo{ String tbSn;// 表序号 String tableName;// 表名 String timeElapsed;// 耗时 public InsertJobInfo(String tbSn,String tableName,String timeElapsed) { this.tbSn=tbSn; this.tableName=tableName; this.timeElapsed=timeElapsed; } } /** * start point * @param args */ public static void main(String[] args) { InsertManager im=new InsertManager(); im.batchInsert(); } }
多线程插表类:
package com.hy.insert.multithread; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import com.hy.DBParam; /** * 删单表线程 * @author 逆火 * * 2019年11月17日 上午9:24:39 */ public class InsertThread extends Thread{ private static Logger log = Logger.getLogger(InsertThread.class); private final int BatchSize=250;// 一次性插入记录数 private int tableIndex;// 表序号 private String tableName;// tablename private int count;// record count will be inserted private String[] innerArr;// array contains field type and names private InsertManager manager;// reference to InsertManager /** * Constructor * @param tableIndex * @param tableName * @param count * @param innerArr * @param mng */ public InsertThread(int tableIndex,String tableName,int count,String[] innerArr,InsertManager mng) { this.tableIndex=tableIndex; this.tableName=tableName; this.count=count; this.innerArr=innerArr; this.manager=mng; } /** * Run body here */ public void run() { Connection conn = null; Statement stmt = null; try{ long startTime = System.currentTimeMillis(); Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); log.info("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"..."); truncateTable(tableName,conn,stmt); insertDataToTable(tableIndex,tableName,count,innerArr,conn,stmt); if(isAllInserted(count,tableName,stmt)) { long endTime = System.currentTimeMillis(); String timeElasped=sec2DHMS(startTime,endTime); log.info("#"+tableIndex+" "+count+" records were inserted to table:'" + tableName + "' used " + timeElasped ); manager.reportFinished(String.valueOf(tableIndex), tableName, timeElasped); } } catch (Exception e) { System.out.print(e.getMessage()); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { log.error("Can't close stmt/conn because of " + e.getMessage()); } } } /** * judge if all records are inserted * @param count * @param table * @param stmt * @return * @throws SQLException */ private boolean isAllInserted(int count,String table,Statement stmt) throws SQLException { String sql="SELECT COUNT (*) as cnt FROM "+table; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int cnt = rs.getInt("cnt"); return cnt==count; } return false; } /** * get datetime n seconds before * @param n * @param interval * @return */ private static String getDatetimeBefore(int n,int interval) { try { Calendar now = Calendar.getInstance(); now.add(Calendar.SECOND,-n*interval);//鏃ユ湡鍑忓幓n*10绉� Date newDate=now.getTime(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String retval = sdf.format(newDate); return retval; } catch(Exception ex) { ex.printStackTrace(); return null; } } /** * delete all data in a table quickly * @param tableName * @param conn * @param stmt * @throws SQLException */ private void truncateTable(String tableName,Connection conn,Statement stmt) throws SQLException{ String sql="truncate table "+tableName; stmt.execute(sql); log.info("truncated table:"+tableName); } /** * Insert date to a table * @param tbSN * @param tableName * @param count * @param innerArr * @param conn * @param stmt * @throws SQLException */ private void insertDataToTable(int tbSN,String tableName,int count,String[] innerArr,Connection conn,Statement stmt) throws SQLException{ // 寰楀埌瀛楁鍚嶅拰瀛楁绫诲瀷 List<TypeField> typefields=new ArrayList<TypeField>(); for(int i=1;i<innerArr.length;i++) { String temp=innerArr[i]; String[] arrTmp=temp.split(":"); TypeField tf=new TypeField(); tf.type=arrTmp[0]; tf.field=arrTmp[1]; typefields.add(tf); } List<String> fields=new ArrayList<String>(); List<String> values=new ArrayList<String>(); int index=0; for(TypeField tf:typefields) { fields.add(tf.field); values.add("''{"+index+"}''"); index++; } int interval=2*365*24*60*60/count;// 涓ゅ勾鐨勭鏁伴櫎浠ユ�讳釜鏁板嵆涓洪棿闅� index=0; int times=count/BatchSize; for(int i=0;i<times;i++) { StringBuilder sb=new StringBuilder(); sb.append("INSERT ALL "); for(int j=0;j<BatchSize;j++) { index=i*BatchSize+j; sb.append(getInsertSql(tableName,typefields,index,interval)); } sb.append(" select * from dual"); String sql = sb.toString(); // long startTime = System.currentTimeMillis(); stmt.executeUpdate(sql); //long endTime = System.currentTimeMillis(); //log.info("#"+tbSN+"-"+i+" "+BatchSize+" records inserted to '"+tableName+"' used " + sec2DHMS(startTime,endTime)); } } /** * get insert sql * @param tableName * @param typefields * @param index * @return */ private String getInsertSql(String tableName,List<TypeField> typefields,int index,int interval) { String currTime=getDatetimeBefore(index,interval); StringBuilder sb=new StringBuilder(); sb.append(" INTO "+tableName+"("); List<String> fields=new ArrayList<String>(); for(TypeField tf:typefields) { fields.add(tf.field); } sb.append(String.join(",",fields)); sb.append(") values("); List<String> values=new ArrayList<String>(); for(TypeField tf:typefields) { if(tf.type.equals("PK")) { //values.add("'"+String.valueOf(index)+"'"); if(tableName.contains("DELIVERY_INFO_HISTORY")) { values.add("'0'"); }else { values.add("'"+String.valueOf(index)+"'"); } }else if(tf.type.equals("CH")) { values.add("'0'"); }else if(tf.type.equals("US")) { values.add("'heyang'"); }else if(tf.type.equals("DT")) { values.add("to_date('"+currTime+"','yyyy-MM-dd HH24:mi:ss')"); } } sb.append(String.join(",",values)); sb.append(")"); String insertSql=sb.toString(); return insertSql; } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } /** * Inner class,used for inner data structure * @author 逆火 * * 2019年11月17日 上午9:27:47 */ protected static final class TypeField{ String type; String field; } }
多线程插表输出:
2019-11-17 09:19:26,915 INFO[Thread-3]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-10]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-13]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-9]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-15]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-5]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-12]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-7]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-11]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,916 INFO[Thread-8]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-4]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-1]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-0]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-14]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-6]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:26,915 INFO[Thread-2]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:19:27,373 INFO[Thread-2]-truncated table:TestTB03 2019-11-17 09:19:27,377 INFO[Thread-11]-truncated table:TestTB12 2019-11-17 09:19:27,380 INFO[Thread-10]-truncated table:TestTB11 2019-11-17 09:19:27,380 INFO[Thread-14]-truncated table:TestTB15 2019-11-17 09:19:27,439 INFO[Thread-6]-truncated table:TestTB07 2019-11-17 09:19:27,439 INFO[Thread-15]-truncated table:TestTB16 2019-11-17 09:19:27,439 INFO[Thread-3]-truncated table:TestTB04 2019-11-17 09:19:27,440 INFO[Thread-12]-truncated table:TestTB13 2019-11-17 09:19:27,439 INFO[Thread-9]-truncated table:TestTB10 2019-11-17 09:19:27,440 INFO[Thread-1]-truncated table:TestTB02 2019-11-17 09:19:27,440 INFO[Thread-8]-truncated table:TestTB09 2019-11-17 09:19:27,439 INFO[Thread-4]-truncated table:TestTB05 2019-11-17 09:19:27,441 INFO[Thread-13]-truncated table:TestTB14 2019-11-17 09:19:27,671 INFO[Thread-7]-truncated table:TestTB08 2019-11-17 09:19:27,677 INFO[Thread-5]-truncated table:TestTB06 2019-11-17 09:19:30,180 INFO[Thread-0]-truncated table:TestTB01 2019-11-17 09:35:42,104 INFO[Thread-14]-#15 100000 records were inserted to table:'TestTB15' used 16m15s 2019-11-17 09:35:42,105 INFO[Thread-14]-1 inserters completed their jobs. 2019-11-17 09:35:50,789 INFO[Thread-9]-#10 100000 records were inserted to table:'TestTB10' used 16m24s 2019-11-17 09:35:50,789 INFO[Thread-9]-2 inserters completed their jobs. 2019-11-17 09:35:51,143 INFO[Thread-2]-#3 100000 records were inserted to table:'TestTB03' used 16m25s 2019-11-17 09:35:51,144 INFO[Thread-2]-3 inserters completed their jobs. 2019-11-17 09:35:54,732 INFO[Thread-6]-#7 100000 records were inserted to table:'TestTB07' used 16m28s 2019-11-17 09:35:54,733 INFO[Thread-6]-4 inserters completed their jobs. 2019-11-17 09:36:01,647 INFO[Thread-1]-#2 100000 records were inserted to table:'TestTB02' used 16m35s 2019-11-17 09:36:01,647 INFO[Thread-1]-5 inserters completed their jobs. 2019-11-17 09:36:01,905 INFO[Thread-11]-#12 100000 records were inserted to table:'TestTB12' used 16m35s 2019-11-17 09:36:01,905 INFO[Thread-11]-6 inserters completed their jobs. 2019-11-17 09:36:02,715 INFO[Thread-0]-#1 100000 records were inserted to table:'TestTB01' used 16m36s 2019-11-17 09:36:02,715 INFO[Thread-0]-7 inserters completed their jobs. 2019-11-17 09:36:04,088 INFO[Thread-10]-#11 100000 records were inserted to table:'TestTB11' used 16m37s 2019-11-17 09:36:04,088 INFO[Thread-10]-8 inserters completed their jobs. 2019-11-17 09:36:04,246 INFO[Thread-15]-#16 100000 records were inserted to table:'TestTB16' used 16m38s 2019-11-17 09:36:04,246 INFO[Thread-15]-9 inserters completed their jobs. 2019-11-17 09:36:06,874 INFO[Thread-7]-#8 100000 records were inserted to table:'TestTB08' used 16m40s 2019-11-17 09:36:06,874 INFO[Thread-7]-10 inserters completed their jobs. 2019-11-17 09:36:08,301 INFO[Thread-13]-#14 100000 records were inserted to table:'TestTB14' used 16m42s 2019-11-17 09:36:08,301 INFO[Thread-13]-11 inserters completed their jobs. 2019-11-17 09:36:08,474 INFO[Thread-3]-#4 100000 records were inserted to table:'TestTB04' used 16m42s 2019-11-17 09:36:08,474 INFO[Thread-3]-12 inserters completed their jobs. 2019-11-17 09:36:08,546 INFO[Thread-4]-#5 100000 records were inserted to table:'TestTB05' used 16m42s 2019-11-17 09:36:08,546 INFO[Thread-4]-13 inserters completed their jobs. 2019-11-17 09:36:09,036 INFO[Thread-8]-#9 100000 records were inserted to table:'TestTB09' used 16m42s 2019-11-17 09:36:09,036 INFO[Thread-8]-14 inserters completed their jobs. 2019-11-17 09:36:09,283 INFO[Thread-5]-#6 100000 records were inserted to table:'TestTB06' used 16m43s 2019-11-17 09:36:09,284 INFO[Thread-5]-15 inserters completed their jobs. 2019-11-17 09:36:11,038 INFO[Thread-12]-#13 100000 records were inserted to table:'TestTB13' used 16m44s 2019-11-17 09:36:11,039 INFO[Thread-12]->>> Insert jobs finished.( time elapsed: 16m44s) <<< 2019-11-17 09:36:11,039 INFO[Thread-12]------------- Details ------------ 2019-11-17 09:36:11,040 INFO[Thread-12]-15,TestTB15,16m15s 2019-11-17 09:36:11,040 INFO[Thread-12]-10,TestTB10,16m24s 2019-11-17 09:36:11,040 INFO[Thread-12]-3,TestTB03,16m25s 2019-11-17 09:36:11,040 INFO[Thread-12]-7,TestTB07,16m28s 2019-11-17 09:36:11,040 INFO[Thread-12]-2,TestTB02,16m35s 2019-11-17 09:36:11,040 INFO[Thread-12]-12,TestTB12,16m35s 2019-11-17 09:36:11,040 INFO[Thread-12]-1,TestTB01,16m36s 2019-11-17 09:36:11,040 INFO[Thread-12]-11,TestTB11,16m37s 2019-11-17 09:36:11,040 INFO[Thread-12]-16,TestTB16,16m38s 2019-11-17 09:36:11,040 INFO[Thread-12]-8,TestTB08,16m40s 2019-11-17 09:36:11,041 INFO[Thread-12]-14,TestTB14,16m42s 2019-11-17 09:36:11,041 INFO[Thread-12]-4,TestTB04,16m42s 2019-11-17 09:36:11,041 INFO[Thread-12]-5,TestTB05,16m42s 2019-11-17 09:36:11,041 INFO[Thread-12]-9,TestTB09,16m42s 2019-11-17 09:36:11,041 INFO[Thread-12]-6,TestTB06,16m43s 2019-11-17 09:36:11,041 INFO[Thread-12]-13,TestTB13,16m44s 2019-11-17 09:36:11,041 INFO[Thread-12]------------- Details ------------
单线程删表类:
package com.hy.delete.singlethread; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.log4j.Logger; import com.hy.DBParam; /** * 多表单线程删除 * Single thread table deleter * @author 逆火 * * 2019年11月17日 上午8:42:41 */ public class BatchDeleter { private static Logger log = Logger.getLogger(BatchDeleter.class); // Commit size private static final int commitSize=10000; private String[] tablenames= { "TestTB01", "TestTB02", "TestTB03", "TestTB04", "TestTB05", "TestTB06", "TestTB07", "TestTB08", "TestTB09", "TestTB10", "TestTB11", "TestTB12", "TestTB13", "TestTB14", "TestTB15", "TestTB16", }; /** * 批量插入 */ public void batchDelete(String expiredDate) { Connection conn = null; Statement stmt = null; try{ Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); System.out.println("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"..."); int index=1; for(String table:tablenames) { int total=delete(index,table,expiredDate,conn,stmt); log.info("#"+index+" "+total+" records deleted from table:'"+table+"'."); index++; } } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { log.error("Can't close stmt/conn because of " + e.getMessage()); } } } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } /** * 按日期删一张表的记录 * @param tableIndex * @param table * @param expiredDate * @param conn * @param stmt * @throws SQLException */ private int delete(int tableIndex,String table,String expiredDate,Connection conn,Statement stmt) throws SQLException { int totalDeleted=0; int expiredCount=0; do { String sql="delete from "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<'"+commitSize+"' "; int deleted=stmt.executeUpdate(sql); //log.info("#"+tableIndex+" "+deleted+" records deleted from table:'"+table+"'."); totalDeleted+=deleted; expiredCount=queryExpiredCount(table,expiredDate,stmt); }while(expiredCount>0); return totalDeleted; } /** * 查询过期记录数量 * @param table * @param expiredDate * @param conn * @param stmt * @return * @throws SQLException */ private int queryExpiredCount(String table,String expiredDate,Statement stmt) throws SQLException { String sql="SELECT COUNT (*) as cnt FROM "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<10 "; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int count = rs.getInt("cnt"); return count; } return 0; } public static void main(String[] args) { long startTime = System.currentTimeMillis(); BatchDeleter bd=new BatchDeleter(); bd.batchDelete("2019-07-17"); long endTime = System.currentTimeMillis(); log.info("Time elapsed:" + sec2DHMS(startTime,endTime) ); } }
多线程删表管理器类:
package com.hy.insert.multithread; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; /** * 多线程批量插入管理者 * @author 逆火 * * 2019年11月17日 上午9:19:09 */ public class InsertManager { private static Logger log = Logger.getLogger(InsertManager.class); private final int TotalInsert=100000;// 单表插入总记录数 private List<InsertJobInfo> jobInfos;// 插表信息集合 private long startTime;// Start time // 要插入的表数组 private final String[][] tableArray= { {"TestTB01:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB02:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB03:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB04:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB05:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB06:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB07:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB08:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB09:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB10:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB11:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB12:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB13:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB14:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB15:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, {"TestTB16:"+TotalInsert,"PK:ID","CH:NAME","CH:AGE","DT:CREATEDTIME"}, }; /** * 启动线程进行批量插入 */ public void batchInsert() { startTime=System.currentTimeMillis(); jobInfos=new ArrayList<InsertJobInfo>(); int index=1; for(String[] innerArr:tableArray) { String tableName=innerArr[0].split(":")[0]; int count=Integer.parseInt(innerArr[0].split(":")[1]); new InsertThread(index,tableName,count,innerArr,this).start(); index++; } } /** * Thread report manager "job done." * @param tbSN * @param tableName * @param timeElasped */ public void reportFinished(String tbSN,String tableName,String timeElasped) { jobInfos.add(new InsertJobInfo(tbSN,tableName,timeElasped)); if(jobInfos.size()==tableArray.length) { long endTime = System.currentTimeMillis(); log.info(">>> Insert jobs finished.( time elapsed: " + sec2DHMS(startTime,endTime)+") <<<"); log.info("------------ Details ------------"); for(InsertJobInfo jobInfo:jobInfos) { String raw="{0},{1},{2}"; Object[] arr={jobInfo.tbSn,jobInfo.tableName,jobInfo.timeElapsed}; String line=MessageFormat.format(raw, arr); log.info(line); } log.info("------------ Details ------------"); }else { log.info(jobInfos.size()+" inserters completed their jobs."); } } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } /** * 成员内部类,用来做数据结构 * @author 逆火 * * 2019年11月17日 上午9:22:04 */ protected static final class InsertJobInfo{ String tbSn;// 表序号 String tableName;// 表名 String timeElapsed;// 耗时 public InsertJobInfo(String tbSn,String tableName,String timeElapsed) { this.tbSn=tbSn; this.tableName=tableName; this.timeElapsed=timeElapsed; } } /** * start point * @param args */ public static void main(String[] args) { InsertManager im=new InsertManager(); im.batchInsert(); } }
多线程删表类:
package com.hy.insert.multithread; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import com.hy.DBParam; /** * 删单表线程 * @author 逆火 * * 2019年11月17日 上午9:24:39 */ public class InsertThread extends Thread{ private static Logger log = Logger.getLogger(InsertThread.class); private final int BatchSize=250;// 一次性插入记录数 private int tableIndex;// 表序号 private String tableName;// tablename private int count;// record count will be inserted private String[] innerArr;// array contains field type and names private InsertManager manager;// reference to InsertManager /** * Constructor * @param tableIndex * @param tableName * @param count * @param innerArr * @param mng */ public InsertThread(int tableIndex,String tableName,int count,String[] innerArr,InsertManager mng) { this.tableIndex=tableIndex; this.tableName=tableName; this.count=count; this.innerArr=innerArr; this.manager=mng; } /** * Run body here */ public void run() { Connection conn = null; Statement stmt = null; try{ long startTime = System.currentTimeMillis(); Class.forName(DBParam.Driver).newInstance(); conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd); stmt = conn.createStatement(); log.info("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"..."); truncateTable(tableName,conn,stmt); insertDataToTable(tableIndex,tableName,count,innerArr,conn,stmt); if(isAllInserted(count,tableName,stmt)) { long endTime = System.currentTimeMillis(); String timeElasped=sec2DHMS(startTime,endTime); log.info("#"+tableIndex+" "+count+" records were inserted to table:'" + tableName + "' used " + timeElasped ); manager.reportFinished(String.valueOf(tableIndex), tableName, timeElasped); } } catch (Exception e) { System.out.print(e.getMessage()); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { log.error("Can't close stmt/conn because of " + e.getMessage()); } } } /** * judge if all records are inserted * @param count * @param table * @param stmt * @return * @throws SQLException */ private boolean isAllInserted(int count,String table,Statement stmt) throws SQLException { String sql="SELECT COUNT (*) as cnt FROM "+table; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int cnt = rs.getInt("cnt"); return cnt==count; } return false; } /** * get datetime n seconds before * @param n * @param interval * @return */ private static String getDatetimeBefore(int n,int interval) { try { Calendar now = Calendar.getInstance(); now.add(Calendar.SECOND,-n*interval);//鏃ユ湡鍑忓幓n*10绉� Date newDate=now.getTime(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String retval = sdf.format(newDate); return retval; } catch(Exception ex) { ex.printStackTrace(); return null; } } /** * delete all data in a table quickly * @param tableName * @param conn * @param stmt * @throws SQLException */ private void truncateTable(String tableName,Connection conn,Statement stmt) throws SQLException{ String sql="truncate table "+tableName; stmt.execute(sql); log.info("truncated table:"+tableName); } /** * Insert date to a table * @param tbSN * @param tableName * @param count * @param innerArr * @param conn * @param stmt * @throws SQLException */ private void insertDataToTable(int tbSN,String tableName,int count,String[] innerArr,Connection conn,Statement stmt) throws SQLException{ // 寰楀埌瀛楁鍚嶅拰瀛楁绫诲瀷 List<TypeField> typefields=new ArrayList<TypeField>(); for(int i=1;i<innerArr.length;i++) { String temp=innerArr[i]; String[] arrTmp=temp.split(":"); TypeField tf=new TypeField(); tf.type=arrTmp[0]; tf.field=arrTmp[1]; typefields.add(tf); } List<String> fields=new ArrayList<String>(); List<String> values=new ArrayList<String>(); int index=0; for(TypeField tf:typefields) { fields.add(tf.field); values.add("''{"+index+"}''"); index++; } int interval=2*365*24*60*60/count;// 涓ゅ勾鐨勭鏁伴櫎浠ユ�讳釜鏁板嵆涓洪棿闅� index=0; int times=count/BatchSize; for(int i=0;i<times;i++) { StringBuilder sb=new StringBuilder(); sb.append("INSERT ALL "); for(int j=0;j<BatchSize;j++) { index=i*BatchSize+j; sb.append(getInsertSql(tableName,typefields,index,interval)); } sb.append(" select * from dual"); String sql = sb.toString(); // long startTime = System.currentTimeMillis(); stmt.executeUpdate(sql); //long endTime = System.currentTimeMillis(); //log.info("#"+tbSN+"-"+i+" "+BatchSize+" records inserted to '"+tableName+"' used " + sec2DHMS(startTime,endTime)); } } /** * get insert sql * @param tableName * @param typefields * @param index * @return */ private String getInsertSql(String tableName,List<TypeField> typefields,int index,int interval) { String currTime=getDatetimeBefore(index,interval); StringBuilder sb=new StringBuilder(); sb.append(" INTO "+tableName+"("); List<String> fields=new ArrayList<String>(); for(TypeField tf:typefields) { fields.add(tf.field); } sb.append(String.join(",",fields)); sb.append(") values("); List<String> values=new ArrayList<String>(); for(TypeField tf:typefields) { if(tf.type.equals("PK")) { //values.add("'"+String.valueOf(index)+"'"); if(tableName.contains("DELIVERY_INFO_HISTORY")) { values.add("'0'"); }else { values.add("'"+String.valueOf(index)+"'"); } }else if(tf.type.equals("CH")) { values.add("'0'"); }else if(tf.type.equals("US")) { values.add("'heyang'"); }else if(tf.type.equals("DT")) { values.add("to_date('"+currTime+"','yyyy-MM-dd HH24:mi:ss')"); } } sb.append(String.join(",",values)); sb.append(")"); String insertSql=sb.toString(); return insertSql; } /** * change seconds to DayHourMinuteSecond format * @param stratMs * @param endMs * @return */ private static String sec2DHMS(long stratMs,long endMs) { String retval = null; long secondCount=(endMs-stratMs)/1000; long days = secondCount / (60 * 60 * 24); long hours = (secondCount % (60 * 60 * 24)) / (60 * 60); long minutes = (secondCount % (60 * 60)) / 60; long seconds = secondCount % 60; if (days > 0) { retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s"; } else if (hours > 0) { retval = hours + "h" + minutes + "m" + seconds + "s"; } else if (minutes > 0) { retval = minutes + "m" + seconds + "s"; } else { retval = seconds + "s"; } return retval; } /** * Inner class,used for inner data structure * @author 逆火 * * 2019年11月17日 上午9:27:47 */ protected static final class TypeField{ String type; String field; } }
多线程删表结果:
2019-11-17 11:10:04,728 INFO[Thread-2]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,728 INFO[Thread-4]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-11]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-10]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-14]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-9]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-5]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-7]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-13]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-12]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-15]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-8]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-3]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,728 INFO[Thread-1]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,729 INFO[Thread-6]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:04,728 INFO[Thread-0]-Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 11:10:30,721 INFO[Thread-14]-#15 83075 records deleted from table:'TestTB15'. 2019-11-17 11:10:30,725 INFO[Thread-14]-1 deleters completed their jobs. 2019-11-17 11:10:31,798 INFO[Thread-12]-#13 83075 records deleted from table:'TestTB13'. 2019-11-17 11:10:31,799 INFO[Thread-12]-2 deleters completed their jobs. 2019-11-17 11:10:33,649 INFO[Thread-9]-#10 83075 records deleted from table:'TestTB10'. 2019-11-17 11:10:33,649 INFO[Thread-9]-3 deleters completed their jobs. 2019-11-17 11:10:33,684 INFO[Thread-7]-#8 83075 records deleted from table:'TestTB08'. 2019-11-17 11:10:33,684 INFO[Thread-7]-4 deleters completed their jobs. 2019-11-17 11:10:35,740 INFO[Thread-0]-#1 83075 records deleted from table:'TestTB01'. 2019-11-17 11:10:35,740 INFO[Thread-0]-5 deleters completed their jobs. 2019-11-17 11:10:36,836 INFO[Thread-13]-#14 83075 records deleted from table:'TestTB14'. 2019-11-17 11:10:36,836 INFO[Thread-13]-6 deleters completed their jobs. 2019-11-17 11:10:36,932 INFO[Thread-8]-#9 83075 records deleted from table:'TestTB09'. 2019-11-17 11:10:36,932 INFO[Thread-8]-7 deleters completed their jobs. 2019-11-17 11:10:37,011 INFO[Thread-2]-#3 83075 records deleted from table:'TestTB03'. 2019-11-17 11:10:37,011 INFO[Thread-2]-8 deleters completed their jobs. 2019-11-17 11:10:38,479 INFO[Thread-5]-#6 83075 records deleted from table:'TestTB06'. 2019-11-17 11:10:38,479 INFO[Thread-5]-9 deleters completed their jobs. 2019-11-17 11:10:40,565 INFO[Thread-11]-#12 83075 records deleted from table:'TestTB12'. 2019-11-17 11:10:40,565 INFO[Thread-10]-#11 83075 records deleted from table:'TestTB11'. 2019-11-17 11:10:40,565 INFO[Thread-4]-#5 83075 records deleted from table:'TestTB05'. 2019-11-17 11:10:40,566 INFO[Thread-10]-11 deleters completed their jobs. 2019-11-17 11:10:40,566 INFO[Thread-11]-10 deleters completed their jobs. 2019-11-17 11:10:40,567 INFO[Thread-4]-12 deleters completed their jobs. 2019-11-17 11:10:40,633 INFO[Thread-15]-#16 83075 records deleted from table:'TestTB16'. 2019-11-17 11:10:40,633 INFO[Thread-15]-13 deleters completed their jobs. 2019-11-17 11:10:41,558 INFO[Thread-3]-#4 83075 records deleted from table:'TestTB04'. 2019-11-17 11:10:41,558 INFO[Thread-3]-14 deleters completed their jobs. 2019-11-17 11:10:42,127 INFO[Thread-6]-#7 83075 records deleted from table:'TestTB07'. 2019-11-17 11:10:42,127 INFO[Thread-6]-15 deleters completed their jobs. 2019-11-17 11:10:42,229 INFO[Thread-1]-#2 83075 records deleted from table:'TestTB02'. 2019-11-17 11:10:42,230 INFO[Thread-1]->>> Delete jobs finished.( time elapsed: 38s) <<< 2019-11-17 11:10:42,230 INFO[Thread-1]------------- Details ------------ 2019-11-17 11:10:42,231 INFO[Thread-1]-#,table,deleted,time elapsed 2019-11-17 11:10:42,234 INFO[Thread-1]-15,TestTB15,83075 2019-11-17 11:10:42,235 INFO[Thread-1]-13,TestTB13,83075 2019-11-17 11:10:42,235 INFO[Thread-1]-10,TestTB10,83075 2019-11-17 11:10:42,235 INFO[Thread-1]-8,TestTB08,83075 2019-11-17 11:10:42,236 INFO[Thread-1]-1,TestTB01,83075 2019-11-17 11:10:42,236 INFO[Thread-1]-14,TestTB14,83075 2019-11-17 11:10:42,237 INFO[Thread-1]-9,TestTB09,83075 2019-11-17 11:10:42,237 INFO[Thread-1]-3,TestTB03,83075 2019-11-17 11:10:42,238 INFO[Thread-1]-6,TestTB06,83075 2019-11-17 11:10:42,238 INFO[Thread-1]-12,TestTB12,83075 2019-11-17 11:10:42,239 INFO[Thread-1]-11,TestTB11,83075 2019-11-17 11:10:42,239 INFO[Thread-1]-5,TestTB05,83075 2019-11-17 11:10:42,241 INFO[Thread-1]-16,TestTB16,83075 2019-11-17 11:10:42,260 INFO[Thread-1]-4,TestTB04,83075 2019-11-17 11:10:42,262 INFO[Thread-1]-7,TestTB07,83075 2019-11-17 11:10:42,262 INFO[Thread-1]-2,TestTB02,83075 2019-11-17 11:10:42,262 INFO[Thread-1]------------- Details ------------
--END-- 2019年11月17日11:51:07
【Oracle/Java】多表插删数据单多线程比较的更多相关文章
- 十四、oracle 数据库管理--管理表空间和数据文件
一.概念表空间是数据库的逻辑组成部分.从物理上讲,数据库数据存放在数据文件中:从逻辑上讲,数据库数据则是存放在表空间中,表空间由一个或多个数据文件组成. 二.数据库的逻辑结构oracle中逻辑结构包括 ...
- oracle 数据库管理--管理表空间和数据文件
一.概念表空间是数据库的逻辑组成部分.从物理上讲,数据库数据存放在数据文件中:从逻辑上讲,数据库数据则是存放在表空间中,表空间由一个或多个数据文件组成. 二.数据库的逻辑结构oracle中逻辑结构包括 ...
- Oracle移除表空间的数据文件 ora-00604 ora-01426
项目背景:在之前开发环境数据库管理比較乱,在表空间不足时仅仅是加入数据文件,測试完后数据己删除,但数据库表空间所占的空间不能回收,导致数据库的存储文件夹使用率达到97%以上实际使用仅仅有10%, ...
- Oracle查看所有表空间的数据使用情况
-- 查看所有表空间的数据使用情况 SELECT Upper(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)& ...
- Oracle 删除大表中部分数据
需求: 项目中有一张表大概有7000多万条数据,造成表空间已满,需要清理部分数据,打算清理3000万. 2B 做法: delete from table_name where ID > '400 ...
- oracle中修改表已有数据的某一列的字段类型的方法,数据备份
1.在开发过程中经常会遇到表中的某一个字段数据类型不对,比如说需要保存的数据带小数,但是在最初设计的时候是给的number(10)类型,开始保存是整数的时候满足要求,后来在保存小数的时候 会发现自动四 ...
- 【oracle】迁表结构和数据
背景:把一些表和数据从某库迁到另一个库 1.命令框: exp yktsh/yktsh_2019@orcl30 file=d:\yktsh20191201.dmp log=d:\daochu; exp ...
- 【基础】Oracle 表空间和数据文件
多个表空间的优势:1.能够将数据字典与用户数据分离出来,避免由于字典对象和用户对象保存在同一个数据文件中而产生的I/O冲突2.能够将回退数据与用户数据分离出来,避免由于硬盘损坏而导致永久性的数据丢失3 ...
- Oracle备份表结构和数据
--创建一份表结构 create table BASE_GOODSPAYMENT_SETTING_BAK as select * from BASE_GOODSPAYMENT_SETTING ; -- ...
随机推荐
- JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql
JDBC终章- 使用 DBUtils实现增删查改 1.数据库结构 Create Table CREATE TABLE `user` ( `id` ) NOT NULL AUTO_INCREMENT, ...
- 0017SpringBoot注册Servlet三大组件(Servlet、Filter、Listener)
由于SpringBoot默认是以jar包的形式启动嵌入式servlet容器来启动SpringBoot的web应用,所以没有web.xml文件,那么如何配置Servlet.Filter.Listener ...
- puppeteer报错 UnhandledPromiseRejectionWarning: Error: Protocol error (Page.getLayoutMetrics): Target closed.
puppeteer运行时报错: UnhandledPromiseRejectionWarning: Error: Protocol error (Page.getLayoutMetrics): Tar ...
- go语言的内建变量类型
string bool int int8 int16 int32 int64 uintptr 无符号int 类型 (u)int (u)int8 (u)int16 (u)int32 (u)int ...
- Java直接内存读写的例子
在Hotspot JVM上,我们能够直接对内存进行读写操作.该类的allocateMemory方法用于申请分配内存,putAddress和getAddress方法用于对直接内存进行读写. 本文将通过s ...
- 数据库删除数据 truncate 与 delete
delete from table where 直接删除表中的某一行数据,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作.所以delete相比较truncate更加占用资源,数据 ...
- loj #2316
最短路 + 记忆化 记忆化搜索更容易实现 #include <iostream> #include <cstdio> #include <algorithm> #i ...
- [Luogu] 受欢迎的牛
https://www.luogu.org/problemnew/show/P2341 Tarjan 缩点 + 判断出度 #include <iostream> #include < ...
- CSPS2019游(tuifei)记
%%%脸哥没脸%%% Day0,日常考前紧张,做不下题去.听各大主任送祝福(从里红(wa)到外) 然后就出发了,大巴上和云力一起坐,吃了好多东西.中午因不满火车站的不合理收费,选择了面包+火腿 下午在 ...
- centos7haproxy+keepalive
1部署keepalived 1.1下载keepalived源码包,并解压# wget http://www.keepalived.org/software/keepalived-1.4.2.tar.g ...