一、Mysql批量删除大量数据

方案1

假设有一个表(syslogs)有1000万条记录,需要在业务不停止的情况下删除其中statusid=1的所有记录,差不多有600万条, 直接执行 DELETE FROM syslogs WHERE statusid=1 会发现删除失败,因为lock wait timeout exceed的错误。

因为这条语句所涉及的记录数太多,因此我们通过LIMIT参数分批删除,比如每10000条进行一次删除,那么我们可以利用 MySQL这样的语句来完成:

DELETE FROM syslogs WHERE status=1 ORDER BY statusid LIMIT 10000;

如果要用order by 必须要和 limit 联用,否则被优化掉。然后分多次执行就可以把这些记录成功删除。

注意:
执行大批量删除的时候注意要使用上limit。因为如果不用limit,删除大量数据很有可能造成死锁。
如果delete的where语句不在索引上,可以先找主键,然后根据主键删除数据库。
平时update和delete的时候最好也加上limit 1 来防止误操作。

方案2

1.删除大表的部分数据
一个表有1亿6000万的数据,有一个自增ID。最大值就是1亿6000万,需要删除大于250万以后的数据,有什么办法可以快速删除?

看到mysql文档有一种解决方案:http://dev.mysql.com/doc/refman/5.0/en/delete.html

If you are deleting many rows from a large table, you may exceed the lock table size for an InnoDB table. To avoid this problem, or simply to minimize the time that the table remains locked, the following strategy (which does not use DELETE at all) might be helpful:

    Select the rows not to be deleted into an empty table that has the same structure as the original table:INSERT INTO t_copy SELECT * FROM t WHERE ... ;Use RENAME TABLE to atomically move the original table out of the way and rename the copy to the original name:RENAME TABLE t TO t_old, t_copy TO t;Drop the original table:DROP TABLE t_old;

删除大表的多行数据时,会超出innod block table size的限制,最小化的减少锁表的时间的方案是:
1、选择不需要删除的数据,并把它们存在一张相同结构的空表里
2、重命名原始表,并给新表命名为原始表的原始表名
3、删掉原始表

方案3

在My SQL数据库使用中,有的表存储数据量比较大,达到每天三百万条记录左右,此表中建立了三个索引,这些索引都是必须的,其他程序要使用。由于要求此表中的数据只保留当天的数据,所以每当在凌晨的某一时刻当其他程序处理完其中的数据后要删除该表中昨天以及以前的数据,使用delete删除表中的上百万条记录时,MySQL删除速度非常缓慢,每一万条记录需要大概4分钟左右,这样删除所有无用数据要达到八个小时以上,这是难以接受的。

查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的,于是删除掉其中的两个索引后测试,发现此时删除速度相当快,一百万条记录在一分钟多一些,可是这两个索引其他模块在每天一次的数据整理中还要使用,于是想到了一个折中的办法:

在删除数据之前删除这两个索引,此时需要三分钟多一些,然后删除其中无用数据,此过程需要不到两分钟,删除完成后重新创建索引,因为此时数据库中的数据相对较少,约三四十万条记录(此表中的数据每小时会增加约十万条),创建索引也非常快,约十分钟左右。这样整个删除过程只需要约15分钟。对比之前的八个小时,大大节省了时间。

方案四

异步批量删除,每次删除固定数量数据

List<Long> searchData;//查询出的要删除的数据
MarketSearchMapper marketSearchMapper;
Integer batchNums = 1000;//每个批次数量
List<List<Long>> idsList = ListUtils.partition(searchData,batchNums);
for(List<Long> ids : idsList){CompletableFuture.runAsync(() -> marketSearchMapper.deleteByIds(ids);//marketSearchMapper的批量删除方法)
}//或者利用流进行删除
idsList.stream().forEach(ids-> {arketSearchMapper.deleteByIds(ids);//marketSearchMapper的批量删除方法});

Java 使用线程池和CountDownLatch分批插入或者更新数据

/*** 分页操作数据*/
@Slf4j
@Component
public class BatchDealDemo  {private void batchDeal(List data, int batchNum) throws InterruptedException {int totalNum = data.size();int pageNum = totalNum % batchNum == 0 ? totalNum / batchNum : totalNum / batchNum + 1;ExecutorService executor = Executors.newFixedThreadPool(pageNum);//或者用ThreadPoolExecutor线程池//private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());log.info("主线程开始执行 begin --- ");try {CountDownLatch countDownLatch = new CountDownLatch(pageNum);List subData = null;int fromIndex, toIndex;for (int i = 0; i < pageNum; i++) {fromIndex = i * batchNum;toIndex = Math.min(totalNum, fromIndex + batchNum);subData = data.subList(fromIndex, toIndex);ImportTask task = new ImportTask(subData, countDownLatch);executor.execute(task);}// 当前线程必须在执行完任务之后立即调用CountDownLatch.await()方法,// 这样主线程的操作就会被阻塞,直到全部子线程完成各自的任务。//  CountDownLatch类中计数器的值等于0时,主线程就能通过await()方法恢复执行自己的任务。countDownLatch.await();log.info("数据操作完成!可以在此开始主线程的其它业务");log.info("主线程执行完毕 end --- ");} finally {// 关闭线程池,释放资源executor.shutdown();}}class ImportTask implements Runnable {private List list;private CountDownLatch countDownLatch;public ImportTask(List data, CountDownLatch countDownLatch) {this.list = data;this.countDownLatch = countDownLatch;}@Overridepublic void run() {if (null != list) {// 业务逻辑,例如批量insert或者updatelog.info("现在操作的数据是{}", list);}// 发出子线程任务完成的信号countDownLatch.countDown();}}
}

线程池同步删除

 try {long start = System.currentTimeMillis();List<NameZ> list = createList();Integer batchNums = 1000;//每个批次数量List<List<NameZ>> lists = ListUtils.partition(searchData,batchNums);System.out.println("主线程开始");//创建线程池private static ThreadPoolExecutor executorService= new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());//线程同步围栏CountDownLatch cdl = new CountDownLatch(i);long end = System.currentTimeMillis();System.out.println((end - start)/1000 + "秒");long startList = System.currentTimeMillis();//线程池中取线程 执行集合lists.forEach((a)->executorService.submit(() -> {dealWith(a);cdl.countDown();}));//主线程等待子线程执行完成再继续执行cdl.await();//关闭线程池executorService.shutdown();System.out.println("主线程结束");long endList = System.currentTimeMillis();System.out.println((endList - startList) + "秒");} catch (Exception e) {e.printStackTrace();}

多线程+List分段

public void threadMethod() {List<T> updateList = new ArrayList();// 初始化线程池, 参数一定要一定要一定要调好!!!!ThreadPoolExecutor threadPool = new ThreadPoolExecutor(20, 50,4, TimeUnit.SECONDS, new ArrayBlockingQueue(10), new ThreadPoolExecutor.AbortPolicy());// 大集合拆分成N个小集合, 这里集合的size可以稍微小一些(这里我用100刚刚好), 以保证多线程异步执行, 过大容易回到单线程List<Long> searchData;//查询出的要删除的数据
MarketSearchMapper marketSearchMapper;
Integer batchNums = 1000;//每个批次数量
List<T> splitNList = ListUtils.partition(searchData,batchNums);// 记录单个任务的执行次数CountDownLatch countDownLatch = new CountDownLatch(splitNList.size());// 对拆分的集合进行批量处理, 先拆分的集合, 再多线程执行for (List<T> singleList : splitNList) {// 线程池执行threadPool.execute(new Thread(new Runnable(){@Overridepublic void run() {for (Entity yangshiwen : singleList) {// 将每一个对象进行数据封装, 并添加到一个用于存储更新数据的list// ......}}}));// 任务个数 - 1, 直至为0时唤醒await()countDownLatch.countDown();}try {// 让当前线程处于阻塞状态,直到锁存器计数为零countDownLatch.await();} catch (InterruptedException e) {throw new BusinessLogException(ResponseEnum.FAIL);}// 通过mybatis的批量插入的方式来进行数据的插入, 这一步还是要做判空if (GeneralUtil.listNotNull(updateList)) {batchUpdateEntity(updateList);LogUtil.info("xxxxxxxxxxxxxxx");}
}

二、delete和truncate区别

1、delete删除数据的原理:(delete属于DML语句)

表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放!!!
这种删除表的优点是:支持回滚,后悔了可以恢复数据,可以删除单条数据
缺点:删除效率比较低

delete from user;  //删除user表中的数据,但是这种删除数据的方式有点慢。

2、truncate删除数据的原理:(DDL)

效率比较高,表被一次截断,物理删除
优点:快速,不走事务,不会锁表,也不会产生大量日志写入日志文件
缺点:不支持回滚,只能删除表中所有数据,不能删单条数据
如果说公司项目里面有一张大表,数据非常多,几亿条记录:
删除的时候,使用delete,也许执行一个小时才能删除完,效率极其低;
可以选择使用truncate删除表中的数据。只需要不到1s的时间就能删除结束,效率较高。
但是使用truncate之前,必须仔细询问客户是否真的需要删除,并警告删除之后不可恢复!!!

truncate table user; //删除user表中的数据,快速。

3、删除表操作:

drop table 表名;// 删除表,不是删除表中的数据

truncate和delete是删除表中的数据,表还在。

参考文章
mysql批量删除大量数据
MySQL中快速删除表中的数据
Mysql 大批量删除数据(解决方案)
MySQL删除大批量数据
ListUtils.partition的用法
Java 使用线程池和CountDownLatch分批插入或者更新数据
Java批量更新太慢?多线程+List分段完美解决

Mysql批量删除大量数据相关推荐

  1. mysql进阶(十五) mysql批量删除大量数据

    假设有一个表(syslogs)有1000万条记录,需要在业务不停止的情况下删除其中statusid=1的所有记录,差不多有600万条, 直接执行 DELETE FROM syslogs WHERE s ...

  2. mysql批量删除5000条数据_mysql批量删除大量数据

    mysql批量删除大量数据 假设有一个表(syslogs)有1000万条记录,需要在业务不停止的情况下删除其中statusid=1的所有记录,差不多有600万条, 直接执行 DELETE FROM s ...

  3. MySQL 删除数据 批量删除(大量)数据

    在删除数据的时候根据不同的场景使用不同的方法,比如说删除表中部分数据.删除表的结构.删除所有记录并重置自增ID.批量删除大量数据等,可以使用delete.truncate.drop等语句. 一.方法分 ...

  4. mysql中如何大量删除数据_mysql批量删除大量数据的方法

    mysql批量删除大量数据 假设有一个表(syslogs)有1000万条记录,需要在业务不停止的情况下删除其中statusid=1的所有记录,差不多有600万条, 直接执行 DELETE FROM s ...

  5. mysql 批量删除数据

    批量删除2000w数据 使用delete from table太慢 //DELIMITER DROP PROCEDURE if EXISTS deleteManyTable; create PROCE ...

  6. mysql千万级数据怎么删除,MySQL 快速删除大量数据(千万级别)的几种实践方案详解...

    这篇文章主要介绍了MySQL 快速删除大量数据(千万级别)的几种实践方案详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 笔者 ...

  7. MySQL删除退出后数据未更新,mysql一不小心删除了数据或更新了数据没有加where 条件...

    mysql一不小心删除了数据或更新了数据没有加where 条件 1,show variables like '%log_bin%'; 2.show master logs; 3.show master ...

  8. MySQL 中删除的数据都去哪儿了?

    不知道大家有没有想过下面这件事? 我们平时调用 DELETE 在 MySQL 中删除的数据都去哪儿了? 这还用问吗?当然是被删除了啊 那么这里又有个新的问题了,如果在 InnoDB 下,多事务并发的情 ...

  9. 【十】JDBC:使用 jmeter 批量在数据库创建 1 万多条数据;批量删除重复数据

    目录 一.批量创建1万多条数据 二.批量删除重复数据 一.批量创建1万多条数据 数据库车辆信息表中准备10000多台车的数据: (1)创建线程组,循环1次: (2)连接数据池: (3)添加循环控制器, ...

最新文章

  1. 摘:C/C++中时间类time.h
  2. ABAP日期函数(求月末日,第几周,search help 只显示年月) 使用方法实例
  3. [转]世界十大最美历史遗迹[组图]。
  4. Autofac 之 基于 Castle DynamicProxy2 的 Interceptor 功能
  5. 下一代微服务架构基础:ServiceMesh?
  6. 使用c++查看linux服务器某个进程正在使用的内存_精选20个常用的Linux命令
  7. 开发者调试工具Chrome Workspace
  8. linux重新初始化mysql 并修改大小写铭感_在Linux(Centos 7)环境下安装Mysql的完整过程...
  9. linux下usb无线网卡对比
  10. ant design pro模板_ant design pro超详细入门教程
  11. cad插入块_CAD中创建块与写块的区别总结
  12. 企业微信之网页授权登录
  13. 新手可以操作的日赚50元的网赚项目
  14. 【论文随笔2】COALA: Co-Aligned Autoencoders for Learning Semantically Enriched Audio Representations
  15. 生信技能树linux虚拟机,科学网—Windows10安装Linux子系统Ubuntu 20.04LTS,轻松使用生信软件,效率秒杀虚拟机 - 刘永鑫的博文...
  16. swfobject1.5
  17. Flink 创建流处理运行环境
  18. EXCEL如何合并单元格且保留全部内容
  19. CVPR 2022 | 重新审视池化:你的感受野不是最理想的
  20. 用python打印购物小票和证书

热门文章

  1. luogu P5286 [HNOI2019]鱼
  2. 模拟电路-模拟加法器的设计和仿真
  3. 完美解决cx_oracle连接us7ascii字符集数据库
  4. c++——简单计算器
  5. 生产环境服务端报错:阿里云IOT连接中断
  6. C# 通过网络和三菱的PLC通信
  7. Python量化交易平台开发教程系列5-底层接口对接
  8. FMCW激光雷达科普(上):基本概念、技术路线、优势及争议和误解
  9. xshell 连接报错 Disconnected from remote host
  10. 全年DDoS攻击分析|知道创宇云安全2018年度网络安全态势报告