【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 ; -- ...
随机推荐
- Linux 之 文件
文件名称 在linux中,windows概念中的文件夹和文件是没有区别的,都是统称为文件. 1.Linux中文件的名称大小写是敏感的 2.名称最多可以为255个字符 3.除了正斜线以外,都是有效字符 ...
- python 元类理解
原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...
- Redis4.0之持久化存储
一,redis概述与实验环境说明 1.1 什么是redis redis是一种内存型的NoSQL数据库,优点是快,常用来做缓存用 redis存储数据的方法是以key-value的形式 value类型 ...
- SASS 和 LESS 的区别
1.编译环境不同 SASS 的安装需要 Ruby 环境,是在服务端处理的: LESS 需要引入 less.js 来处理代码输出 CSS 到浏览器,也可以在开发环节使用 LESS,然后编译成 CSS 文 ...
- Select count(*)和Count(1)的区别和执行方式
在SQL Server中Count(*)或者Count(1)或者Count([列])或许是最常用的聚合函数.很多人其实对这三者之间是区分不清的.本文会阐述这三者的作用,关系以及背后的原理. 往常我经常 ...
- 【Java】用五种语言写数组(用于自己学习)
C语言 #include<stdio.h> int main() { ] = {, , , , , , , , , }; int i; ;i<;i++) printf("% ...
- "=="和equals小结
通俗点讲,==是看看左右是不是一个东西.equals是看看左右是不是长得一样.如何记住嘛.如果单纯是想记住, ==:等于.equals:相同.两个长得一样的人,只能说长的相同(equals),但是不 ...
- go语言的内建变量类型
string bool int int8 int16 int32 int64 uintptr 无符号int 类型 (u)int (u)int8 (u)int16 (u)int32 (u)int ...
- Selenium常用API的使用java语言之16-下拉框选择
有时我们会碰到下拉框,WebDriver提供了Select类来处理下接框. 如百度搜索设置的下拉框,如下图: 搜索下拉框实现代码如下: <select id="nr" nam ...
- c语言之——整型的隐式转换与溢出检测
溢出检测 我们可以通过下面的方式来检测溢出: if(a > INT_MAX - b) { printf("overflow\n"); } 我们利用整型的最大值减去其中 ...