昨天做了插入的单线程多线程比较,今天做个删除的。

单线程批量删除类代码:

  1. package com.hy.delete.singlethread;
  2.  
  3. import java.sql.Connection;
  4. import java.sql.DriverManager;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. import java.sql.Statement;
  8.  
  9. import org.apache.log4j.Logger;
  10.  
  11. import com.hy.DBParam;
  12.  
  13. /**
  14. * 多表单线程删除
  15. * Single thread table deleter
  16. * @author 逆火
  17. *
  18. * 2019年11月17日 上午8:42:41
  19. */
  20. public class BatchDeleter {
  21. private static Logger log = Logger.getLogger(BatchDeleter.class);
  22.  
  23. // Commit size
  24. private static final int commitSize=10000;
  25.  
  26. private String[] tablenames= { "TestTB01",
  27. "TestTB02",
  28. "TestTB03",
  29. "TestTB04",
  30. "TestTB05",
  31. "TestTB06",
  32. "TestTB07",
  33. "TestTB08",
  34. "TestTB09",
  35. "TestTB10",
  36. "TestTB11",
  37. "TestTB12",
  38. "TestTB13",
  39. "TestTB14",
  40. "TestTB15",
  41. "TestTB16",
  42. };
  43.  
  44. /**
  45. * 批量插入
  46. */
  47. public void batchDelete(String expiredDate) {
  48. Connection conn = null;
  49. Statement stmt = null;
  50.  
  51. try{
  52. Class.forName(DBParam.Driver).newInstance();
  53. conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd);
  54. stmt = conn.createStatement();
  55. System.out.println("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"...");
  56.  
  57. int index=1;
  58. for(String table:tablenames) {
  59. int total=delete(index,table,expiredDate,conn,stmt);
  60. log.info("#"+index+" "+total+" records deleted from table:'"+table+"'.");
  61. index++;
  62. }
  63. } catch (Exception e) {
  64. e.printStackTrace();
  65. } finally {
  66. try {
  67. stmt.close();
  68. conn.close();
  69. } catch (SQLException e) {
  70. log.error("Can't close stmt/conn because of " + e.getMessage());
  71. }
  72. }
  73. }
  74.  
  75. /**
  76. * change seconds to DayHourMinuteSecond format
  77. * @param stratMs
  78. * @param endMs
  79. * @return
  80. */
  81. private static String sec2DHMS(long stratMs,long endMs) {
  82. String retval = null;
  83. long secondCount=(endMs-stratMs)/1000;
  84.  
  85. long days = secondCount / (60 * 60 * 24);
  86. long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
  87. long minutes = (secondCount % (60 * 60)) / 60;
  88. long seconds = secondCount % 60;
  89.  
  90. if (days > 0) {
  91. retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
  92. } else if (hours > 0) {
  93. retval = hours + "h" + minutes + "m" + seconds + "s";
  94. } else if (minutes > 0) {
  95. retval = minutes + "m" + seconds + "s";
  96. } else {
  97. retval = seconds + "s";
  98. }
  99.  
  100. return retval;
  101. }
  102.  
  103. /**
  104. * 按日期删一张表的记录
  105. * @param tableIndex
  106. * @param table
  107. * @param expiredDate
  108. * @param conn
  109. * @param stmt
  110. * @throws SQLException
  111. */
  112. private int delete(int tableIndex,String table,String expiredDate,Connection conn,Statement stmt) throws SQLException {
  113. int totalDeleted=0;
  114. int expiredCount=0;
  115.  
  116. do {
  117. String sql="delete from "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<'"+commitSize+"' ";
  118. int deleted=stmt.executeUpdate(sql);
  119. //log.info("#"+tableIndex+" "+deleted+" records deleted from table:'"+table+"'.");
  120. totalDeleted+=deleted;
  121.  
  122. expiredCount=queryExpiredCount(table,expiredDate,stmt);
  123. }while(expiredCount>0);
  124.  
  125. return totalDeleted;
  126. }
  127.  
  128. /**
  129. * 查询过期记录数量
  130. * @param table
  131. * @param expiredDate
  132. * @param conn
  133. * @param stmt
  134. * @return
  135. * @throws SQLException
  136. */
  137. private int queryExpiredCount(String table,String expiredDate,Statement stmt) throws SQLException {
  138. String sql="SELECT COUNT (*) as cnt FROM "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<10 ";
  139.  
  140. ResultSet rs = stmt.executeQuery(sql);
  141.  
  142. while (rs.next()) {
  143. int count = rs.getInt("cnt");
  144. return count;
  145. }
  146.  
  147. return 0;
  148. }
  149.  
  150. public static void main(String[] args) {
  151. long startTime = System.currentTimeMillis();
  152. BatchDeleter bd=new BatchDeleter();
  153. bd.batchDelete("2019-07-17");
  154. long endTime = System.currentTimeMillis();
  155. log.info("Time elapsed:" + sec2DHMS(startTime,endTime) );
  156. }
  157. }

输出:

  1. Begin to access jdbc:oracle:thin:@127.0.0.1:1521:orcl as ufo...
  2. 2019-11-17 09:40:44,951 INFO[main]-#1 83077 records deleted from table:'TestTB01'.
  3. 2019-11-17 09:40:46,165 INFO[main]-#2 83077 records deleted from table:'TestTB02'.
  4. 2019-11-17 09:40:49,874 INFO[main]-#3 83077 records deleted from table:'TestTB03'.
  5. 2019-11-17 09:40:53,271 INFO[main]-#4 83077 records deleted from table:'TestTB04'.
  6. 2019-11-17 09:40:56,728 INFO[main]-#5 83077 records deleted from table:'TestTB05'.
  7. 2019-11-17 09:40:59,420 INFO[main]-#6 83077 records deleted from table:'TestTB06'.
  8. 2019-11-17 09:41:02,766 INFO[main]-#7 83077 records deleted from table:'TestTB07'.
  9. 2019-11-17 09:41:05,983 INFO[main]-#8 83077 records deleted from table:'TestTB08'.
  10. 2019-11-17 09:41:08,704 INFO[main]-#9 83077 records deleted from table:'TestTB09'.
  11. 2019-11-17 09:41:11,827 INFO[main]-#10 83077 records deleted from table:'TestTB10'.
  12. 2019-11-17 09:41:14,895 INFO[main]-#11 83077 records deleted from table:'TestTB11'.
  13. 2019-11-17 09:41:18,155 INFO[main]-#12 83077 records deleted from table:'TestTB12'.
  14. 2019-11-17 09:41:20,941 INFO[main]-#13 83077 records deleted from table:'TestTB13'.
  15. 2019-11-17 09:41:23,992 INFO[main]-#14 83077 records deleted from table:'TestTB14'.
  16. 2019-11-17 09:41:25,462 INFO[main]-#15 83077 records deleted from table:'TestTB15'.
  17. 2019-11-17 09:41:28,066 INFO[main]-#16 83077 records deleted from table:'TestTB16'.
  18. 2019-11-17 09:41:28,068 INFO[main]-Time elapsed:45s

多线程批量删除管理者类:

  1. package com.hy.delete.multithread;
  2.  
  3. import java.text.MessageFormat;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6.  
  7. import org.apache.log4j.Logger;
  8.  
  9. /**
  10. * 批量删表管理者
  11. * @author 逆火
  12. *
  13. * 2019年11月17日 上午9:54:46
  14. */
  15. public class DeleteManager {
  16. private static Logger log = Logger.getLogger(DeleteManager.class);
  17.  
  18. private String[] tablenames= { "TestTB01",
  19. "TestTB02",
  20. "TestTB03",
  21. "TestTB04",
  22. "TestTB05",
  23. "TestTB06",
  24. "TestTB07",
  25. "TestTB08",
  26. "TestTB09",
  27. "TestTB10",
  28. "TestTB11",
  29. "TestTB12",
  30. "TestTB13",
  31. "TestTB14",
  32. "TestTB15",
  33. "TestTB16",
  34. };
  35.  
  36. private long startTime;// Start time
  37.  
  38. private List<DeleteJobInfo> jobInfos;// delete table informations
  39.  
  40. /**
  41. * 批量插入
  42. */
  43. public void batchDelete(String expiredDate) {
  44. startTime=System.currentTimeMillis();
  45. jobInfos=new ArrayList<DeleteJobInfo>();
  46.  
  47. int index=1;
  48. for(String table:tablenames) {
  49. DeleteThread dt=new DeleteThread(index,table,expiredDate,this);
  50. dt.start();
  51. index++;
  52. }
  53. }
  54.  
  55. /**
  56. * Thread report manager "job done."
  57. * @param tbSN
  58. * @param tableName
  59. * @param timeElasped
  60. */
  61. public void reportFinished(String tbSN,String tableName,String timeElasped,String deleted) {
  62. jobInfos.add(new DeleteJobInfo(tbSN,tableName,timeElasped,deleted));
  63.  
  64. if(jobInfos.size()==tablenames.length) {
  65. long endTime = System.currentTimeMillis();
  66. log.info(">>> Delete jobs finished.( time elapsed: " + sec2DHMS(startTime,endTime)+") <<<");
  67.  
  68. log.info("------------ Details ------------");
  69. log.info("#,table,deleted,time elapsed");
  70. for(DeleteJobInfo jobInfo:jobInfos) {
  71. String raw="{0},{1},{2}";
  72. Object[] arr={jobInfo.tbSn,jobInfo.tableName,jobInfo.deleted,jobInfo.timeElapsed};
  73. String line=MessageFormat.format(raw, arr);
  74. log.info(line);
  75. }
  76. log.info("------------ Details ------------");
  77.  
  78. }else {
  79. log.info(jobInfos.size()+" deleters completed their jobs.");
  80. }
  81. }
  82.  
  83. /**
  84. * 成员内部类,用来做数据结构
  85. * 参考:https://blog.csdn.net/weixin_42762133/article/details/82890555
  86. * @author 逆火
  87. *
  88. * 2019年11月17日 上午9:22:04
  89. */
  90. protected static final class DeleteJobInfo{
  91. String tbSn;// 表序号
  92. String tableName;// 表名
  93. String timeElapsed;// 耗时
  94. String deleted;// count of deleted records
  95.  
  96. public DeleteJobInfo(String tbSn,String tableName,String timeElapsed,String deleted) {
  97. this.tbSn=tbSn;
  98. this.tableName=tableName;
  99. this.timeElapsed=timeElapsed;
  100. this.deleted=deleted;
  101. }
  102. }
  103.  
  104. /**
  105. * change seconds to DayHourMinuteSecond format
  106. * @param stratMs
  107. * @param endMs
  108. * @return
  109. */
  110. private static String sec2DHMS(long stratMs,long endMs) {
  111. String retval = null;
  112. long secondCount=(endMs-stratMs)/1000;
  113.  
  114. long days = secondCount / (60 * 60 * 24);
  115. long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
  116. long minutes = (secondCount % (60 * 60)) / 60;
  117. long seconds = secondCount % 60;
  118.  
  119. if (days > 0) {
  120. retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
  121. } else if (hours > 0) {
  122. retval = hours + "h" + minutes + "m" + seconds + "s";
  123. } else if (minutes > 0) {
  124. retval = minutes + "m" + seconds + "s";
  125. } else {
  126. retval = seconds + "s";
  127. }
  128.  
  129. return retval;
  130. }
  131.  
  132. public static void main(String[] args) {
  133. DeleteManager dm=new DeleteManager();
  134. dm.batchDelete("2019-07-17");
  135. }
  136. }

多线程删除删除者类:

  1. package com.hy.delete.multithread;
  2.  
  3. import java.sql.Connection;
  4. import java.sql.DriverManager;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. import java.sql.Statement;
  8.  
  9. import org.apache.log4j.Logger;
  10.  
  11. import com.hy.DBParam;
  12.  
  13. public class DeleteThread extends Thread {
  14. private static Logger log = Logger.getLogger(DeleteThread.class);
  15.  
  16. // Commit size
  17. private static final int commitSize=10000;
  18.  
  19. private int tableIndex;// table serial number
  20. private String table;// table will be deleted
  21. private String expiredDate;// expired date
  22. private DeleteManager menager; // reference to manager
  23.  
  24. public DeleteThread(int tableIndex,String table,String expiredDate,DeleteManager menager) {
  25. this.tableIndex=tableIndex;
  26. this.table=table;
  27. this.expiredDate=expiredDate;
  28. this.menager=menager;
  29. }
  30.  
  31. public void run() {
  32. Connection conn = null;
  33. Statement stmt = null;
  34.  
  35. try{
  36. long startTime = System.currentTimeMillis();
  37.  
  38. Class.forName(DBParam.Driver).newInstance();
  39. conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd);
  40. stmt = conn.createStatement();
  41. log.info("Begin to access "+DBParam.DbUrl+" as "+DBParam.User+"...");
  42.  
  43. int total=delete(tableIndex,table,expiredDate,conn,stmt);
  44. log.info("#"+tableIndex+" "+total+" records deleted from table:'"+table+"'.");
  45.  
  46. long endTime = System.currentTimeMillis();
  47. String timeElasped=sec2DHMS(startTime,endTime);
  48. menager.reportFinished(String.valueOf(tableIndex), table, timeElasped,String.valueOf(total));
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. } finally {
  52. try {
  53. stmt.close();
  54. conn.close();
  55. } catch (SQLException e) {
  56. log.error("Can't close stmt/conn because of " + e.getMessage());
  57. }
  58. }
  59. }
  60.  
  61. /**
  62. * 按日期删一张表的记录
  63. * @param tableIndex
  64. * @param table
  65. * @param expiredDate
  66. * @param conn
  67. * @param stmt
  68. * @throws SQLException
  69. */
  70. private int delete(int tableIndex,String table,String expiredDate,Connection conn,Statement stmt) throws SQLException {
  71. int totalDeleted=0;
  72. int expiredCount=0;
  73.  
  74. do {
  75. String sql="delete from "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<'"+commitSize+"' ";
  76. int deleted=stmt.executeUpdate(sql);
  77. //log.info("#"+tableIndex+" "+deleted+" records deleted from table:'"+table+"'.");
  78. totalDeleted+=deleted;
  79.  
  80. expiredCount=queryExpiredCount(table,expiredDate,stmt);
  81. }while(expiredCount>0);
  82.  
  83. return totalDeleted;
  84. }
  85.  
  86. /**
  87. * 查询过期记录数量
  88. * @param table
  89. * @param expiredDate
  90. * @param conn
  91. * @param stmt
  92. * @return
  93. * @throws SQLException
  94. */
  95. private int queryExpiredCount(String table,String expiredDate,Statement stmt) throws SQLException {
  96. String sql="SELECT COUNT (*) as cnt FROM "+table+" WHERE CREATEDTIME < to_date('"+expiredDate+"','yyyy-MM-dd') and rownum<10 ";
  97.  
  98. ResultSet rs = stmt.executeQuery(sql);
  99.  
  100. while (rs.next()) {
  101. int count = rs.getInt("cnt");
  102. return count;
  103. }
  104.  
  105. return 0;
  106. }
  107.  
  108. /**
  109. * change seconds to DayHourMinuteSecond format
  110. * @param stratMs
  111. * @param endMs
  112. * @return
  113. */
  114. private static String sec2DHMS(long stratMs,long endMs) {
  115. String retval = null;
  116. long secondCount=(endMs-stratMs)/1000;
  117.  
  118. long days = secondCount / (60 * 60 * 24);
  119. long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
  120. long minutes = (secondCount % (60 * 60)) / 60;
  121. long seconds = secondCount % 60;
  122.  
  123. if (days > 0) {
  124. retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
  125. } else if (hours > 0) {
  126. retval = hours + "h" + minutes + "m" + seconds + "s";
  127. } else if (minutes > 0) {
  128. retval = minutes + "m" + seconds + "s";
  129. } else {
  130. retval = seconds + "s";
  131. }
  132.  
  133. return retval;
  134. }
  135. }

这个例子也证明了多线程相对于单线程的优势。

--END-- 2019年11月17日11:24:17

【Oracle/Java】批量删除16张十万数据的表 单线程耗时45秒 多线程耗时38秒的更多相关文章

  1. 在Oracle中快速创建一张百万级别的表,一张十万级别的表 并修改两表中1%的数据 全部运行时间66秒

    万以下小表做性能优化没有多大意义,因此我需要创建大表: 创建大表有三种方法,一种是insert into table selec..connect by.的方式,它最快但是数据要么是连续值,要么是随机 ...

  2. mybatis(二)接口编程 、动态sql 、批量删除 、动态更新、连表查询

    原理等不在赘述,这里主要通过代码展现. 在mybatis(一)基础上,新建一个dao包,并在里面编写接口,然后再在xml文件中引入接口路径,其他不变,在运用阶段将比原始方法更节约时间,因为不用再去手动 ...

  3. oracle数据库,怎么给已有数据的表添加自增字段

    场景:数据仓库,ODI为使用Oracle Incremental Update IKM,需要对一事实表增加主键. 思想:基于老表创建新表,添加自增字段(序列+触发器实现),把老数据导入新表,删除老表, ...

  4. php批量删除数据库下指定前缀的表

    如何用php批量删除数据库下所有前缀为prefix_的表. 例子,统一删除前缀为“prefix_”的表. <?php //设置数据库连接信息.数据库服务器地址,数据库用户名,数据密码 mysql ...

  5. Mysql批量删除和修改某个前缀的表

    1.批量删除某个前缀的表名,首先选出这些个表. select concat( 'drop table ', table_name, ';' ) from information_schema.tabl ...

  6. 【Oracle/Java】给十六张表各插入十万条数据 单线程耗时半小时 多线程耗时一刻钟

    测试机Oracle版本: SQL> select * from v$version; BANNER ----------------------------------------------- ...

  7. 【Oracle/Java】向三张表各插入百万数据,共用时18分3秒,平均每张表6分钟

    三张表DDL如下: CREATE TABLE tb01 ( "ID" ,) not null primary key, "NAME" NVARCHAR2() n ...

  8. Java 批量删除Word中的空白段落

    1. 测试文档.期望达到的目标文档效果 用于测试的Word文档如下所示,包含的空白段落影响文章整体布局及美观性: 目标文档效果: 2. 辅助工具 2.1 使用类库:Free Spire.Doc for ...

  9. java 批量插入10万条数据

    for (int i = 0; i < 100000; i++) { dbHelper.insert("INSERT aaa(name) Values ('1')"); } ...

随机推荐

  1. ELK文档--ELK简介

    请参考:http://www.cnblogs.com/aresxin/p/8035137.html

  2. 前端框架开始学习Vue(三)

    初步安装.与搭建    https://www.cnblogs.com/yanxulan/p/8978732.html ----如何搭建一个vue项目 安装 nodejs,,, npm i == np ...

  3. HTML&CSS基础-清除浮动

    HTML&CSS基础-清除浮动 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看浮动效果 1>.HTML源代码 <!DOCTYPE html> &l ...

  4. HDU-1237- 简单计算器--栈的基本应用

    简单计算器 Problem Description 读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值.   Input 测试输入包含若干测试用例,每个测试用例占一行,每行不 ...

  5. 集成百度编辑器 ueditor 后端配置项没有正常加载,上传插件不能正常使用!

    项目要用到编辑器,于是集成了ueditor,集成ok,但一直显示 ‘’后端配置项没有正常加载,上传插件不能正常使用!‘’ 各种查: 网上说的无非就是那么集中情况 1. 因为百度官方的问题,php/co ...

  6. P2P system: Napster

    Napster structure client machines之所以叫peers是因为对于server来说这些machines是平等对待的 当你upload一首歌曲如PennyLane.mp3时, ...

  7. flask 杂记3

    SQLAlchemy在模型之间建立关系模式:  https://www.bbsmax.com/A/mo5k7gKn5w/ 一对多时:外键只能存储单一数据(标量),所以外键总是在“多”这一侧定义,多篇文 ...

  8. vue 数组更新检测注意事项

  9. clean()方法的简单应用

    clean()方法主要用于验证相互依赖的字段,例如注册时,填写的“密码”和“确认密码”要相等时才符合要求. 在调用表单clean() 方法的时候,所有字段的验证方法已经执行完(表单字段的默认验证(如C ...

  10. IDEA解决maven多module出现多root的问题

    背景 maven多module项目,maven窗口显示多个root 问题原因 打开父模块pom.xml文件,检查<modules/>标签,发现没有将子模块项目放到<modules/& ...