【Oracle/Java】批量删除16张十万数据的表 单线程耗时45秒 多线程耗时38秒
昨天做了插入的单线程多线程比较,今天做个删除的。
单线程批量删除类代码:
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) ); } }
输出:
Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo... 2019-11-17 09:40:44,951 INFO[main]-#1 83077 records deleted from table:'TestTB01'. 2019-11-17 09:40:46,165 INFO[main]-#2 83077 records deleted from table:'TestTB02'. 2019-11-17 09:40:49,874 INFO[main]-#3 83077 records deleted from table:'TestTB03'. 2019-11-17 09:40:53,271 INFO[main]-#4 83077 records deleted from table:'TestTB04'. 2019-11-17 09:40:56,728 INFO[main]-#5 83077 records deleted from table:'TestTB05'. 2019-11-17 09:40:59,420 INFO[main]-#6 83077 records deleted from table:'TestTB06'. 2019-11-17 09:41:02,766 INFO[main]-#7 83077 records deleted from table:'TestTB07'. 2019-11-17 09:41:05,983 INFO[main]-#8 83077 records deleted from table:'TestTB08'. 2019-11-17 09:41:08,704 INFO[main]-#9 83077 records deleted from table:'TestTB09'. 2019-11-17 09:41:11,827 INFO[main]-#10 83077 records deleted from table:'TestTB10'. 2019-11-17 09:41:14,895 INFO[main]-#11 83077 records deleted from table:'TestTB11'. 2019-11-17 09:41:18,155 INFO[main]-#12 83077 records deleted from table:'TestTB12'. 2019-11-17 09:41:20,941 INFO[main]-#13 83077 records deleted from table:'TestTB13'. 2019-11-17 09:41:23,992 INFO[main]-#14 83077 records deleted from table:'TestTB14'. 2019-11-17 09:41:25,462 INFO[main]-#15 83077 records deleted from table:'TestTB15'. 2019-11-17 09:41:28,066 INFO[main]-#16 83077 records deleted from table:'TestTB16'. 2019-11-17 09:41:28,068 INFO[main]-Time elapsed:45s
多线程批量删除管理者类:
package com.hy.delete.multithread; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; /** * 批量删表管理者 * @author 逆火 * * 2019年11月17日 上午9:54:46 */ public class DeleteManager { private static Logger log = Logger.getLogger(DeleteManager.class); private String[] tablenames= { "TestTB01", "TestTB02", "TestTB03", "TestTB04", "TestTB05", "TestTB06", "TestTB07", "TestTB08", "TestTB09", "TestTB10", "TestTB11", "TestTB12", "TestTB13", "TestTB14", "TestTB15", "TestTB16", }; private long startTime;// Start time private List<DeleteJobInfo> jobInfos;// delete table informations /** * 批量插入 */ public void batchDelete(String expiredDate) { startTime=System.currentTimeMillis(); jobInfos=new ArrayList<DeleteJobInfo>(); int index=1; for(String table:tablenames) { DeleteThread dt=new DeleteThread(index,table,expiredDate,this); dt.start(); index++; } } /** * Thread report manager "job done." * @param tbSN * @param tableName * @param timeElasped */ public void reportFinished(String tbSN,String tableName,String timeElasped,String deleted) { jobInfos.add(new DeleteJobInfo(tbSN,tableName,timeElasped,deleted)); if(jobInfos.size()==tablenames.length) { long endTime = System.currentTimeMillis(); log.info(">>> Delete jobs finished.( time elapsed: " + sec2DHMS(startTime,endTime)+") <<<"); log.info("------------ Details ------------"); log.info("#,table,deleted,time elapsed"); for(DeleteJobInfo jobInfo:jobInfos) { String raw="{0},{1},{2}"; Object[] arr={jobInfo.tbSn,jobInfo.tableName,jobInfo.deleted,jobInfo.timeElapsed}; String line=MessageFormat.format(raw, arr); log.info(line); } log.info("------------ Details ------------"); }else { log.info(jobInfos.size()+" deleters completed their jobs."); } } /** * 成员内部类,用来做数据结构 * 参考:https://blog.csdn.net/weixin_42762133/article/details/82890555 * @author 逆火 * * 2019年11月17日 上午9:22:04 */ protected static final class DeleteJobInfo{ String tbSn;// 表序号 String tableName;// 表名 String timeElapsed;// 耗时 String deleted;// count of deleted records public DeleteJobInfo(String tbSn,String tableName,String timeElapsed,String deleted) { this.tbSn=tbSn; this.tableName=tableName; this.timeElapsed=timeElapsed; this.deleted=deleted; } } /** * 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; } public static void main(String[] args) { DeleteManager dm=new DeleteManager(); dm.batchDelete("2019-07-17"); } }
多线程删除删除者类:
package com.hy.delete.multithread; 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; public class DeleteThread extends Thread { private static Logger log = Logger.getLogger(DeleteThread.class); // Commit size private static final int commitSize=10000; private int tableIndex;// table serial number private String table;// table will be deleted private String expiredDate;// expired date private DeleteManager menager; // reference to manager public DeleteThread(int tableIndex,String table,String expiredDate,DeleteManager menager) { this.tableIndex=tableIndex; this.table=table; this.expiredDate=expiredDate; this.menager=menager; } 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+"..."); int total=delete(tableIndex,table,expiredDate,conn,stmt); log.info("#"+tableIndex+" "+total+" records deleted from table:'"+table+"'."); long endTime = System.currentTimeMillis(); String timeElasped=sec2DHMS(startTime,endTime); menager.reportFinished(String.valueOf(tableIndex), table, timeElasped,String.valueOf(total)); } 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()); } } } /** * 按日期删一张表的记录 * @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; } /** * 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; } }
这个例子也证明了多线程相对于单线程的优势。
--END-- 2019年11月17日11:24:17
【Oracle/Java】批量删除16张十万数据的表 单线程耗时45秒 多线程耗时38秒的更多相关文章
- 在Oracle中快速创建一张百万级别的表,一张十万级别的表 并修改两表中1%的数据 全部运行时间66秒
万以下小表做性能优化没有多大意义,因此我需要创建大表: 创建大表有三种方法,一种是insert into table selec..connect by.的方式,它最快但是数据要么是连续值,要么是随机 ...
- mybatis(二)接口编程 、动态sql 、批量删除 、动态更新、连表查询
原理等不在赘述,这里主要通过代码展现. 在mybatis(一)基础上,新建一个dao包,并在里面编写接口,然后再在xml文件中引入接口路径,其他不变,在运用阶段将比原始方法更节约时间,因为不用再去手动 ...
- oracle数据库,怎么给已有数据的表添加自增字段
场景:数据仓库,ODI为使用Oracle Incremental Update IKM,需要对一事实表增加主键. 思想:基于老表创建新表,添加自增字段(序列+触发器实现),把老数据导入新表,删除老表, ...
- php批量删除数据库下指定前缀的表
如何用php批量删除数据库下所有前缀为prefix_的表. 例子,统一删除前缀为“prefix_”的表. <?php //设置数据库连接信息.数据库服务器地址,数据库用户名,数据密码 mysql ...
- Mysql批量删除和修改某个前缀的表
1.批量删除某个前缀的表名,首先选出这些个表. select concat( 'drop table ', table_name, ';' ) from information_schema.tabl ...
- 【Oracle/Java】给十六张表各插入十万条数据 单线程耗时半小时 多线程耗时一刻钟
测试机Oracle版本: SQL> select * from v$version; BANNER ----------------------------------------------- ...
- 【Oracle/Java】向三张表各插入百万数据,共用时18分3秒,平均每张表6分钟
三张表DDL如下: CREATE TABLE tb01 ( "ID" ,) not null primary key, "NAME" NVARCHAR2() n ...
- Java 批量删除Word中的空白段落
1. 测试文档.期望达到的目标文档效果 用于测试的Word文档如下所示,包含的空白段落影响文章整体布局及美观性: 目标文档效果: 2. 辅助工具 2.1 使用类库:Free Spire.Doc for ...
- java 批量插入10万条数据
for (int i = 0; i < 100000; i++) { dbHelper.insert("INSERT aaa(name) Values ('1')"); } ...
随机推荐
- nginx 之 https 证书配置
HTTPS原理和作用 为什么需要HTTPS 原因:HTTP不安全 传输数据被中间人盗用.信息泄露 数据内容劫持.篡改 HTTPS协议的实现 对传输内容进行加密以及身份验证 对称加密:加密秘钥和解密秘钥 ...
- Cron 定时任务表达式
Cron Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth M ...
- Linux建立虚拟ip的方法
文章来源 运维公会:Linux建立虚拟ip的方法 1.虚拟ip的介绍 虚拟IP地址(VIP) 是一个不与特定计算机或一个计算机中的网络接口卡(NIC)相连的IP地址.数据包被发送到这个VIP地址, ...
- Windows Server 2008更改SID
参考:Windows Server 2012 克隆修改SID 前言 克隆(软克隆,硬克隆)虚拟机后,虚拟机不光名称一样,IP一样(设置静态IP情况下),连SID也一样 什么是SID SID 安全标识符 ...
- 剖析.o文件ELF组成
ELF文件结构组成 ①总共13个节 ②每个节都有一个编号.从ELF头开始编号,编号从0开始,编号的作用就是用来索引(找到)不同节的. ③每个.o的都是这样的结构.链接时要做的就是,将ELF格式的.o全 ...
- c++混合使用不同标准编译潜在的问题
最近项目使用的C++的版本到C++11了,但是由于有些静态库(.a)没有源码,因此链接时还在使用非C++11版本的库文件.目前跑了几天,似乎是没出什么问题,但是我还是想说一下这样做有哪些潜在的风险. ...
- BIOS+MBR操作系统引导方式
1. 主引导记录(Master Boot Record,缩写:MBR) 主引导记录又叫做主引导扇区,是计算机开机后启动操作系统时所必须要读取的硬盘首个扇区,它在硬盘上的三维地址为(柱面,磁头,扇区)= ...
- 网上的JAVA语言的某个测试框架
https://github.com/wenchengyao/testLJTT.git 使用maven打包,mvn clean install 在运行的时候,java -jar testLJTT.ja ...
- 瞎扯KMP
瞎扯\(KMP\) 众所周知,\(KMP\)是一种玄学的字符串模式匹配算法. 什么是字符串模式匹配? 通俗的讲,就是统计一个字符串(通常很长)中某个子串(即一段连续的字符)出现的次数或位置.一般来说, ...
- 0021SpringMVC环境搭建及入门程序编写
环境搭建: 1.创建项目 创建maven项目,勾选上Create from archetype,然后选中webapp再点击下一步,如下图: 解决项目创建过慢问题: 在创建maven项目过程中加入一组键 ...